Xamarin.Forms 形状:路径转换

Transform 定义如何将 Path 对象从一个坐标空间转换为另一个坐标空间。 将转换应用于 Path 对象时,它会更改对象在 UI 中的呈现方式。

转换可分为四种常规分类:旋转、缩放、倾斜和平移。 Xamarin.Forms 为这些转换分类中的每一个定义一个类:

  • RotateTransform,旋转由 Angle 指定的 Path
  • ScaleTransform,将 Path 对象按指定的 ScaleXScaleY 数量缩放。
  • SkewTransform,对 Path 对象按照指定的 AngleXAngleY 数量进行倾斜。
  • TranslateTransform,将 Path 对象按照指定的 XY 数量进行移动。

为了创建更复杂的转换,Xamarin.Forms 还提供了以下类:

  • TransformGroup,表示由多个转换对象组成的复合转换。
  • CompositeTransform,将多个转换操作应用于 Path 对象。
  • MatrixTransform,创建其他转换类不提供的自定义转换。

所有这些类都派生自定义 Value 属性(类型为 Matrix)的 Transform 类,该属性将当前转换表示为 Matrix 对象。 此属性由 BindableProperty 对象提供支持,这意味着它可以作为数据绑定的目标,并进行样式设置。 要详细了解 Matrix 结构,请参阅转换矩阵

要将转换应用于 Path,请创建转换类,并将其设置为 Path.RenderTransform 属性的值。

旋转转换

旋转转换将 Path 对象围绕二维 x-y 坐标系中的指定点顺时针旋转。

派生自 Transform 类的 RotateTransform 类定义以下属性:

  • Angle,类型为 double,表示顺时针旋转的角度(以度为单位)。 此属性的默认值为 0.0。
  • CenterX,类型为 double,表示旋转中心点的 x 坐标。 此属性的默认值为 0.0。
  • CenterY,类型为 double,表示旋转中心点的 y 坐标。 此属性的默认值为 0.0。

这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。

CenterXCenterY 属性指定 Path 对象绕其旋转的点。 此中心点以转换对象的坐标空间表示。 默认情况下,旋转应用于 (0,0),即 Path 对象的左上角。

以下示例演示如何旋转 Path 对象:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <RotateTransform CenterX="0"
                         CenterY="0"
                         Angle="45" />
    </Path.RenderTransform>
</Path>

在此示例中,Path 对象围绕其左上角旋转 45 度。

缩放转换

缩放转换在二维 x-y 坐标系中缩放 Path 对象。

派生自 Transform 类的 ScaleTransform 类定义以下属性:

  • ScaleX,类型为 double,表示 x 轴缩放因子。 此属性的默认值为 1.0。
  • ScaleY,类型为 double,表示 y 轴缩放因子。 此属性的默认值为 1.0。
  • CenterX,类型为 double,表示此转换中心点的 x 坐标。 此属性的默认值为 0.0。
  • CenterY,类型为 double,表示此转换中心点的 y 坐标。 此属性的默认值为 0.0。

这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。

ScaleXScaleY 的值对生成的缩放有巨大影响:

  • 值介于 0 和 1 之间时会减少缩放对象的宽度和高度。
  • 值大于 1 时会增加缩放对象的宽度和高度。
  • 值为 1 时指示对象未缩放。
  • 负值将缩放对象水平和垂直翻转。
  • 值介于 0 和 -1 之间时翻转缩放对象并减小其宽度和高度。
  • 值小于 -1 时翻转对象并增加其宽度和高度。
  • 值为 -1 时可翻转缩放对象,但不更改其水平或垂直大小。

CenterXCenterY 属性指定 Path 对象围绕其缩放的点。 此中心点以转换对象的坐标空间表示。 默认情况下,缩放应用于 (0,0),即 Path 对象的左上角。 这样做的效果是移动 Path 对象并使其看起来更大,因为在应用转换时会更改 Path 对象所在的坐标空间。

以下示例演示如何缩放 Path 对象:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <ScaleTransform CenterX="0"
                        CenterY="0"
                        ScaleX="1.5"
                        ScaleY="1.5" />
    </Path.RenderTransform>
</Path>

在此示例中,Path 对象的大小缩放为 1.5 倍。

倾斜转换

倾斜转换在二维 x-y 坐标系中倾斜 Path 对象,对在二维对象中创建三维深度错觉非常有用。

派生自 Transform 类的 SkewTransform 类定义以下属性:

  • AngleX,类型为 double,表示 x 轴倾斜角,该角度从 y 轴逆时针测量得到(以度为单位)。 此属性的默认值为 0.0。
  • AngleY,类型为 double,表示 y 轴倾斜角,该角度从 x 轴逆时针测量得到(以度为单位)。 此属性的默认值为 0.0。
  • CenterX,类型为 double,表示转换中心的 x 坐标。 此属性的默认值为 0.0。
  • CenterY,类型为 double,表示转换中心的 y 坐标。 此属性的默认值为 0.0。

这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。

若要预测扭曲转换的效果,请考虑 AngleX 相对于原始坐标系统扭曲 x 轴的值。 因此,当 AngleX 为 30 时,y 轴将绕原点旋转 30 度,并将 x 轴的值从该原点倾斜 30 度。 同样地,当 AngleY 为 30 时,Path 对象的 y 值将从原点倾斜 30 度。

注意

要将 Path 对象原地倾斜,请将 CenterXCenterY 属性设置为对象的中心点。

以下示例演示如何倾斜 Path 对象:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <SkewTransform CenterX="0"
                       CenterY="0"
                       AngleX="45"
                       AngleY="0" />
    </Path.RenderTransform>
</Path>

在以下示例中,从中心点 (0,0) 对 Path 对象应用 45 度水平倾斜。

平移转换

平移转换在二维 x-y 坐标系中移动对象。

派生自 Transform 类的 TranslateTransform 类定义以下属性:

  • X,类型为 double,表示沿 x 轴移动的距离。 此属性的默认值为 0.0。
  • Y,类型为 double,表示要沿 y 轴移动的距离。 此属性的默认值为 0.0。

这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。

X 的负值将对象向左移动,而正值将对象向右移动。 Y 的负值将对象向上移动,而正值将对象向下移动。

以下示例演示如何平移 Path 对象:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <TranslateTransform X="50"
                            Y="50" />
    </Path.RenderTransform>
</Path>

在此示例中,Path 对象向右移动 50 个与设备无关的单位,并向下移动 50 个与设备无关的单位。

多重转换

Xamarin.Forms 有两个支持对 Path 对象应用多种转换的类。 它们是 TransformGroupCompositeTransformTransformGroup 按任意所需顺序执行转换,而 CompositeTransform 按特定顺序执行转换。

转换组

转换组表示由多个 Transform 对象组成的复合转换。

派生自 Transform 类的 TransformGroup 类定义类型为 TransformCollectionChildren 属性,该属性表示 Transform 对象的集合。 此属性由 BindableProperty 对象提供支持,这意味着它可以作为数据绑定的目标,并进行样式设置。

转换顺序在使用 TransformGroup 类的复合转换中非常重要。 例如,“先旋转再缩放后平移”与“先平移再旋转后缩放”得到的结果并不一样。 顺序之所以重要,原因之一就是旋转和缩放等转换是相对于坐标系原点执行的。 缩放以原点为中心的对象生成的结果不同于缩放远离原点的对象生成的结果。 同样,旋转以原点为中心的对象产生的结果不同于旋转远离原点的对象所产生的结果。

以下示例演示如何使用 TransformGroup 类执行复合转换:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <TransformGroup>
            <ScaleTransform ScaleX="1.5"
                            ScaleY="1.5" />
            <RotateTransform Angle="45" />
        </TransformGroup>
    </Path.RenderTransform>
</Path>

在此示例中,Path 对象缩放到其大小的 1.5 倍,然后旋转 45 度。

复合转换

复合转换将多重转换应用于对象。

派生自 Transform 类的 CompositeTransform 类定义以下属性:

  • CenterX,类型为 double,表示此转换中心点的 x 坐标。 此属性的默认值为 0.0。
  • CenterY,类型为 double,表示此转换中心点的 y 坐标。 此属性的默认值为 0.0。
  • ScaleX,类型为 double,表示 x 轴缩放因子。 此属性的默认值为 1.0。
  • ScaleY,类型为 double,表示 y 轴缩放因子。 此属性的默认值为 1.0。
  • SkewX,类型为 double,表示 x 轴倾斜角,该角度从 y 轴逆时针测量得到(以度为单位)。 此属性的默认值为 0.0。
  • SkewY,类型为 double,表示 y 轴倾斜角,该角度从 x 轴逆时针测量得到(以度为单位)。 此属性的默认值为 0.0。
  • Rotation,类型为 double,表示顺时针旋转的角度(以度为单位)。 此属性的默认值为 0.0。
  • TranslateX,类型为 double,表示要沿 x 轴移动的距离。 此属性的默认值为 0.0。
  • TranslateY,类型为 double,表示要沿 y 轴移动的距离。 此属性的默认值为 0.0。

这些属性由 BindableProperty 对象提供支持,表示它们可以是数据绑定的目标,并可以设置样式。

CompositeTransform 按以下顺序应用转换:

  1. 缩放(ScaleXScaleY)。
  2. 倾斜(SkewXSkewY)。
  3. 旋转 (Rotation)。
  4. 平移(TranslateXTranslateY)。

如果要以不同的顺序将多重转换应用于对象,应创建 TransformGroup 并按预期顺序插入转换。

重要

CompositeTransform 对所有转换使用相同的中心点 CenterXCenterY。 如果要为每个转换指定不同的中心点,请使用 TransformGroup

以下示例演示如何使用 CompositeTransform 类执行复合转换:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      HeightRequest="100"
      WidthRequest="100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <CompositeTransform ScaleX="1.5"
                            ScaleY="1.5"
                            Rotation="45"
                            TranslateX="50"
                            TranslateY="50" />
    </Path.RenderTransform>
</Path>

在此示例中,将 Path 对象的大小缩放为 1.5 倍,再旋转 45 度,然后平移 50 个与设备无关的单位。

转换矩阵

可以在 3x3 仿射转换矩阵中描述转换,该矩阵在二维空间中执行转换。 此 3x3 矩阵由 Matrix 结构表示,该结构是三行和三列 double 值的集合。

Matrix 结构定义以下属性:

  • Determinant,类型为 double,获取矩阵的行列式。
  • HasInverse,类型为 bool,指示矩阵是否不可逆。
  • Identity,类型为 Matrix,获取标识矩阵。
  • HasIdentity,类型为 bool,指示矩阵是否为标识矩阵。
  • M11,类型为 double,表示矩阵第一行和第一列的值。
  • M12,类型为 double,表示矩阵第一行和第二列的值。
  • M21,类型为 double,表示矩阵第二行和第一列的值。
  • M22,类型为 double,表示矩阵第二行和第二列的值。
  • OffsetX,类型为 double,表示矩阵第三行和第一列的值。
  • OffsetY,类型为 double,表示矩阵第三行和第二列的值。

OffsetXOffsetY 属性之所以如此命名,是因为它们分别指定沿 x 轴和 y 轴平移坐标空间的量。

此外,Matrix 结构还公开一系列可用于操作矩阵值的方法,包括 AppendInvertMultiplyPrepend 等等。

下表显示了 Xamarin.Forms 矩阵的结构:

M11

M12

0.0

M21

M22

0.0

OffsetX

OffsetY

1.0

注意

由于仿射转换矩阵的最后一列等于 (0,0,1),因此仅需要指定前两列中的成员。

通过操作矩阵值,可以旋转、缩放、倾斜和平移 Path 对象。 例如,如果将 OffsetX 值更改为100,则可以使用它将 Path 对象沿 x 轴移动 100 个与设备无关的单位。 如果将 M22 值更改为 3,则可使用它将 Path 对象的当前高度拉伸三倍。 如果同时更改这两个值,将使 Path 对象沿 x 轴移动 100 个与设备无关的单位,并将其高度拉伸 3 倍。 此外,仿射转换矩阵可以相乘以形成任意数量的线性转换,例如旋转和倾斜,并随之平移。

自定义转换

派生自 Transform 类的 MatrixTransform 类定义类型为 MatrixMatrix 属性,该属性表示定义转换的矩阵。 此属性由 BindableProperty 对象提供支持,这意味着它可以作为数据绑定的目标,并进行样式设置。

任何可用 TranslateTransformScaleTransformRotateTransformSkewTransform 对象描述的转换都可以用 MatrixTransform 来描述。 但是,TranslateTransformScaleTransformRotateTransformSkewTransform 类比在 Matrix 中设置矢量分量更易于概念化。 因此,MatrixTransform 类通常用于创建 RotateTransformScaleTransformSkewTransformTranslateTransform 类不提供的自定义转换。

以下示例演示如何使用 MatrixTransform 转换 Path 对象:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <MatrixTransform>
            <MatrixTransform.Matrix>
                <!-- M11 stretches, M12 skews -->
                <Matrix OffsetX="10"
                        OffsetY="100"
                        M11="1.5"
                        M12="1" />
            </MatrixTransform.Matrix>
        </MatrixTransform>
    </Path.RenderTransform>
</Path>

在此示例中,Path 对象同时在 X 和 Y 维度中被拉伸、倾斜和偏移。

也可采用一种简化形式来编写它,该形式使用 Xamarin.Forms 中内置的类型转换器:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z">
    <Path.RenderTransform>
        <MatrixTransform Matrix="1.5,1,0,1,10,100" />
    </Path.RenderTransform>
</Path>

在此示例中,将 Matrix 属性指定为以逗号分隔的字符串,该字符串由六个成员组成:M11M12M21M22OffsetXOffsetY。 虽然此示例中的成员以逗号分隔,但它们也可以由一个或多个空格分隔。

此外,还可以通过指定六个与 RenderTransform 属性的值相同的成员,来进一步简化前面的示例:

<Path Stroke="Black"
      Aspect="Uniform"
      HorizontalOptions="Center"
      RenderTransform="1.5 1 0 1 10 100"
      Data="M13.908992,16.207977L32.000049,16.207977 32.000049,31.999985 13.908992,30.109983z" />