Xamarin.Forms Shapes: Path transforms

A Transform defines how to transform a Path object from one coordinate space to another coordinate space. When a transform is applied to a Path object, it changes how the object is rendered in the UI.

Transforms can be categorized into four general classifications: rotation, scaling, skew, and translation. Xamarin.Forms defines a class for each of these transform classifications:

  • RotateTransform, which rotates a Path by a specified Angle.
  • ScaleTransform, which scales a Path object by specified ScaleX and ScaleY amounts.
  • SkewTransform, which skews a Path object by specified AngleX and AngleY amounts.
  • TranslateTransform, which moves a Path object by specified X and Y amounts.

Xamarin.Forms also provides the following classes for creating more complex transformations:

  • TransformGroup, which represents a composite transform composed of multiple transform objects.
  • CompositeTransform, which applies multiple transform operations to a Path object.
  • MatrixTransform, which creates custom transforms that are not provided by the other transform classes.

All of these classes derive from the Transform class, which defines a Value property of type Matrix, which represents the current transformation as a Matrix object. This property is backed by a BindableProperty object, which means that it can be the target of data bindings, and styled. For more information about the Matrix struct, see Transform matrix.

To apply a transform to a Path, you create a transform class and set it as the value of the Path.RenderTransform property.

Rotation transform

A rotate transform rotates a Path object clockwise about a specified point in a 2D x-y coordinate system.

The RotateTransform class, which derives from the Transform class, defines the following properties:

  • Angle, of type double, represents the angle, in degrees, of clockwise rotation. The default value of this property is 0.0.
  • CenterX, of type double, represents the x-coordinate of the rotation center point. The default value of this property is 0.0.
  • CenterY, of type double, represents the y-coordinate of the rotation center point. The default value of this property is 0.0.

These properties are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

The CenterX and CenterY properties specify the point about which the Path object is rotated. This center point is expressed in the coordinate space of the object that's transformed. By default, the rotation is applied to (0,0), which is the upper-left corner of the Path object.

The following example shows how to rotate a Path object:

<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>

In this example, the Path object is rotated 45 degrees about its upper-left corner.

Scale transform

A scale transform scales a Path object in the 2D x-y coordinate system.

The ScaleTransform class, which derives from the Transform class, defines the following properties:

  • ScaleX, of type double, which represents the x-axis scale factor. The default value of this property is 1.0.
  • ScaleY, of type double, which represents the y-axis scale factor. The default value of this property is 1.0.
  • CenterX, of type double, which represents the x-coordinate of the center point of this transform. The default value of this property is 0.0.
  • CenterY, of type double, which represents the y-coordinate of the center point of this transform. The default value of this property is 0.0.

These properties are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

The value of ScaleX and ScaleY have a huge impact on the resulting scaling:

  • Values between 0 and 1 decrease the width and height of the scaled object.
  • Values greater than 1 increase the width and height of the scaled object.
  • Values of 1 indicate that the object is not scaled.
  • Negative values flip the scale object horizontally and vertically.
  • Values between 0 and -1 flip the scale object and decrease its width and height.
  • Values less than -1 flip the object and increase its width and height.
  • Values of -1 flip the scaled object but do not change its horizontal or vertical size.

The CenterX and CenterY properties specify the point about which the Path object is scaled. This center point is expressed in the coordinate space of the object that's transformed. By default, scaling is applied to (0,0), which is the upper-left corner of the Path object. This has the effect of moving the Path object and making it appear larger, because when you apply a transform you change the coordinate space in which the Path object resides.

The following example shows how to scale a Path object:

<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>

In this example, the Path object is scaled to 1.5 times the size.

Skew transform

A skew transform skews a Path object in the 2D x-y coordinate system, and is useful for creating the illusion of 3D depth in a 2D object.

The SkewTransform class, which derives from the Transform class, defines the following properties:

  • AngleX, of type double, which represents the x-axis skew angle, which is measured in degrees counterclockwise from the y-axis. The default value of this property is 0.0.
  • AngleY, of type double, which represents the y-axis skew angle, which is measured in degrees counterclockwise from the x-axis. The default value of this property is 0.0.
  • CenterX, of type double, which represents the x-coordinate of the transform center. The default value of this property is 0.0.
  • CenterY, of type double, which represents the y-coordinate of the transform center. The default value of this property is 0.0.

These properties are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

To predict the effect of a skew transformation, consider that AngleX skews x-axis values relative to the original coordinate system. Therefore, for an AngleX of 30, the y-axis rotates 30 degrees through the origin and skews the values in x by 30 degrees from that origin. Similarly, an AngleY of 30 skews the y values of the Path object by 30 degrees from the origin.

Note

To skew a Path object in place, set the CenterX and CenterY properties to the object's center point.

The following example shows how to skew a Path object:

<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>

In this example, a horizontal skew of 45 degrees is applied to the Path object, from a center point of (0,0).

Translate transform

A translate transform moves an object in the 2D x-y coordinate system.

The TranslateTransform class, which derives from the Transform class, defines the following properties:

  • X, of type double, which represents the distance to move along the x-axis. The default value of this property is 0.0.
  • Y, of type double, which represents the distance to move along the y-axis. The default value of this property is 0.0.

These properties are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

Negative X values move an object to the left, while positive values move an object to the right. Negative Y values move an object up, while positive values move an object down.

The following example shows how to translate a Path object:

<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>

In this example, the Path object is moved 50 device-independent units to the right, and 50 device-independent units down.

Multiple transforms

Xamarin.Forms has two classes that support applying multiple transforms to a Path object. These are TransformGroup, and CompositeTransform. A TransformGroup performs transforms in any desired order, while a CompositeTransform performs transforms in a specific order.

Transform groups

Transform groups represent composite transforms composed of multiple Transform objects.

The TransformGroup class, which derives from the Transform class, defines a Children property, of type TransformCollection, which represents a collection of Transform objects. This property is backed by a BindableProperty object, which means that it can be the target of data bindings, and styled.

The order of transformations is important in a composite transform that uses the TransformGroup class. For example, if you first rotate, then scale, then translate, you get a different result than if you first translate, then rotate, then scale. One reason order is significant is that transforms like rotation and scaling are performed respect to the origin of the coordinate system. Scaling an object that is centered at the origin produces a different result to scaling an object that has been moved away from the origin. Similarly, rotating an object that is centered at the origin produces a different result than rotating an object that has been moved away from the origin.

The following example shows how to perform a composite transform using the TransformGroup class:

<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>

In this example, the Path object is scaled to 1.5 times its size, and then rotated by 45 degrees.

Composite transforms

A composite transform applies multiple transforms to an object.

The CompositeTransform class, which derives from the Transform class, defines the following properties:

  • CenterX, of type double, which represents the x-coordinate of the center point of this transform. The default value of this property is 0.0.
  • CenterY, of type double, which represents the y-coordinate of the center point of this transform. The default value of this property is 0.0.
  • ScaleX, of type double, which represents the x-axis scale factor. The default value of this property is 1.0.
  • ScaleY, of type double, which represents the y-axis scale factor. The default value of this property is 1.0.
  • SkewX, of type double, which represents the x-axis skew angle, which is measured in degrees counterclockwise from the y-axis. The default value of this property is 0.0.
  • SkewY, of type double, which represents the y-axis skew angle, which is measured in degrees counterclockwise from the x-axis. The default value of this property is 0.0.
  • Rotation, of type double, represents the angle, in degrees, of clockwise rotation. The default value of this property is 0.0.
  • TranslateX, of type double, which represents the distance to move along the x-axis. The default value of this property is 0.0.
  • TranslateY, of type double, which represents the distance to move along the y-axis. The default value of this property is 0.0.

These properties are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

A CompositeTransform applies transforms in this order:

  1. Scale (ScaleX and ScaleY).
  2. Skew (SkewX and SkewY).
  3. Rotate (Rotation).
  4. Translate (TranslateX, TranslateY).

If you want to apply multiple transforms to an object in a different order, you should create a TransformGroup and insert the transforms in your intended order.

Important

A CompositeTransform uses the same center points, CenterX and CenterY, for all transformations. If you want to specify different center points per transform, use a TransformGroup,

The following example shows how to perform a composite transform using the CompositeTransform class:

<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>

In this example, the Path object is scaled to 1.5 times its size, then rotated by 45 degrees, and then translated by 50 device-independent units.

Transform matrix

A transform can be described in terms of a 3x3 affine transformation matrix, that performs transformations in 2D space. This 3x3 matrix is represented by the Matrix struct, which is a collection of three rows and three columns of double values.

The Matrix struct defines the following properties:

  • Determinant, of type double, which gets the determinant of the matrix.
  • HasInverse, of type bool, which indicates whether the matrix is invertible.
  • Identity, of type Matrix, which gets an identity matrix.
  • HasIdentity, of type bool, which indicates whether the matrix is an identity matrix.
  • M11, of type double, which represents the value of the first row and first column of the matrix.
  • M12, of type double, which represents the value of the first row and second column of the matrix.
  • M21, of type double, which represents the value of the second row and first column of the matrix.
  • M22, of type double, which represents the value of the second row and second column of the matrix.
  • OffsetX, of type double, which represents the value of the third row and first column of the matrix.
  • OffsetY, of type double, which represents the value of the third row and second column of the matrix.

The OffsetX and OffsetY properties are so named because they specify the amount to translate the coordinate space along the x-axis, and y-axis, respectively.

In addition, the Matrix struct exposes a series of methods that can be used to manipulate the matrix values, including Append, Invert, Multiply, Prepend and many more.

The following table shows the structure of a Xamarin.Forms matrix:

M11

M12

0.0

M21

M22

0.0

OffsetX

OffsetY

1.0

Note

An affine transformation matrix has its final column equal to (0,0,1), so only the members in the first two columns need to be specified.

By manipulating matrix values, you can rotate, scale, skew, and translate Path objects. For example, if you change the OffsetX value to 100, you can use it move a Path object 100 device-independent units along the x-axis. If you change the M22 value to 3, you can use it to stretch a Path object to three times its current height. If you change both values, you move the Path object 100 device-independent units along the x-axis and stretch its height by a factor of 3. In addition, affine transformation matrices can be multiplied to form any number of linear transformations, such as rotation and skew, followed by translation.

Custom transforms

The MatrixTransform class, which derives from the Transform class, defines a Matrix property, of type Matrix, which represents the matrix that defines the transformation. This property is backed by a BindableProperty object, which means that it can be the target of data bindings, and styled.

Any transform that you can describe with a TranslateTransform, ScaleTransform, RotateTransform, or SkewTransform object can equally be described by a MatrixTransform. However, the TranslateTransform, ScaleTransform, RotateTransform, and SkewTransform classes are easier to conceptualize than setting the vector components in a Matrix. Therefore, the MatrixTransform class is typically used to create custom transformations that aren't provided by the RotateTransform, ScaleTransform, SkewTransform, or TranslateTransform classes.

The following example shows how to transform a Path object using a MatrixTransform:

<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>

In this example, the Path object is stretched, skewed, and offset in both the X and Y dimensions.

Alternatively, this can be written in a simplified form that uses a type converter that's built into 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>

In this example, the Matrix property is specified as a comma-delimited string consisting of six members: M11, M12, M21, M22, OffsetX, OffsetY. While the members are comma-delimited in this example, they can also be delimited by one or more spaces.

In addition, the previous example can be simplified even further by specifying the same six members as the value of the RenderTransform property:

<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" />