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 aPath
by a specifiedAngle
.ScaleTransform
, which scales aPath
object by specifiedScaleX
andScaleY
amounts.SkewTransform
, which skews aPath
object by specifiedAngleX
andAngleY
amounts.TranslateTransform
, which moves aPath
object by specifiedX
andY
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 aPath
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 typedouble
, represents the angle, in degrees, of clockwise rotation. The default value of this property is 0.0.CenterX
, of typedouble
, represents the x-coordinate of the rotation center point. The default value of this property is 0.0.CenterY
, of typedouble
, 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 typedouble
, which represents the x-axis scale factor. The default value of this property is 1.0.ScaleY
, of typedouble
, which represents the y-axis scale factor. The default value of this property is 1.0.CenterX
, of typedouble
, which represents the x-coordinate of the center point of this transform. The default value of this property is 0.0.CenterY
, of typedouble
, 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 typedouble
, 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 typedouble
, 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 typedouble
, which represents the x-coordinate of the transform center. The default value of this property is 0.0.CenterY
, of typedouble
, 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 typedouble
, which represents the distance to move along the x-axis. The default value of this property is 0.0.Y
, of typedouble
, 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 typedouble
, which represents the x-coordinate of the center point of this transform. The default value of this property is 0.0.CenterY
, of typedouble
, which represents the y-coordinate of the center point of this transform. The default value of this property is 0.0.ScaleX
, of typedouble
, which represents the x-axis scale factor. The default value of this property is 1.0.ScaleY
, of typedouble
, which represents the y-axis scale factor. The default value of this property is 1.0.SkewX
, of typedouble
, 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 typedouble
, 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 typedouble
, represents the angle, in degrees, of clockwise rotation. The default value of this property is 0.0.TranslateX
, of typedouble
, which represents the distance to move along the x-axis. The default value of this property is 0.0.TranslateY
, of typedouble
, 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:
- Scale (
ScaleX
andScaleY
). - Skew (
SkewX
andSkewY
). - Rotate (
Rotation
). - 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 typedouble
, which gets the determinant of the matrix.HasInverse
, of typebool
, which indicates whether the matrix is invertible.Identity
, of typeMatrix
, which gets an identity matrix.HasIdentity
, of typebool
, which indicates whether the matrix is an identity matrix.M11
, of typedouble
, which represents the value of the first row and first column of the matrix.M12
, of typedouble
, which represents the value of the first row and second column of the matrix.M21
, of typedouble
, which represents the value of the second row and first column of the matrix.M22
, of typedouble
, which represents the value of the second row and second column of the matrix.OffsetX
, of typedouble
, which represents the value of the third row and first column of the matrix.OffsetY
, of typedouble
, 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" />