转换概述
本主题介绍如何使用 2D Transform 类旋转、缩放、移动(转换)和倾斜 FrameworkElement 对象。
什么是 Transform?
Transform 定义如何将点从一个坐标空间映射或转换到另一个坐标空间。 此映射由转换 Matrix 来描述,它是一个三行三列 Double 值的集合。
注意
Windows Presentation Foundation (WPF) 使用行主矩阵。 矢量表示为行矢量,而非列矢量。
下表显示了 WPF 矩阵的结构。
2D 转换矩阵
X 轴 | Y 轴 | 仿射转换 |
---|---|---|
M11 默认:1.0 |
M12 默认值:0.0 |
0.0 |
M21 默认值:0.0 |
M22 默认:1.0 |
0.0 |
OffsetX 默认值:0.0 |
OffsetY 默认值:0.0 |
1.0 |
通过操作矩阵值,可以旋转、缩放、倾斜和移动(转换)对象。 例如,如果将第三行第一列的值(OffsetX 值)更改为 100,可使用它来将对象沿 x 轴移动 100 个单位。 如果将第二行第二列中的值更改为 3,可使用它来将对象的当前高度拉伸三倍。 如果同时更改这两个值,将使对象沿 x 轴移动 100 个单位,并将其高度拉伸 3 倍。 由于 Windows Presentation Foundation (WPF) 仅支持仿射转换,因此右边列中的值始终为 0, 0, 1。
尽管 Windows Presentation Foundation (WPF) 使你能够直接操作矩阵值,它还提供多个 Transform 类,以便可以在不知道基础矩阵结构配置情况的情况下转换某个对象。 例如,借助 ScaleTransform 类,通过设置其 ScaleX 和 ScaleY 属性即可缩放对象,而无需操作转换矩阵。 同样,借助 RotateTransform 类,只需设置其 Angle 属性,即可旋转对象。
转换类
Windows Presentation Foundation (WPF) 提供以下 2D Transform 类,可用于常见转换操作:
类 | 说明 | 示例 | 图示 |
---|---|---|---|
RotateTransform | 按指定的 Angle 旋转元素。 | 旋转对象 | |
ScaleTransform | 按指定的 ScaleX 和 ScaleY 量缩放元素。 | 缩放元素 | |
SkewTransform | 按指定的 AngleX 和 AngleY 量倾斜元素。 | 倾斜元素 | |
TranslateTransform | 按指定的 X 和 Y 量移动(转换)元素。 | 转换元素 |
为了创建更复杂的转换,Windows Presentation Foundation (WPF) 提供了以下两个类:
类 | 说明 | 示例 |
---|---|---|
TransformGroup | 将多个 TransformGroup 对象组合成单个 Transform,然后你可以应用它来转换属性。 | 将多个转换应用到对象 |
MatrixTransform | 创建其他 Transform 类不提供的自定义转换。 使用 MatrixTransform 时,可直接操作矩阵。 | 使用 MatrixTransform 创建自定义转换 |
Windows Presentation Foundation (WPF) 还提供 3D 转换。 有关更多信息,请参见 Transform3D 类。
常见转换属性
转换对象的一种方法是声明相应的 Transform 类型,然后将其应用于对象的转换属性。 对象类型不同,转换属性的类型也会不同。 下表列出了几种常用 Windows Presentation Foundation (WPF) 类型及其转换属性。
转换和坐标系
转换对象时,不只是转换对象,还会转换该对象所在的坐标空间。 默认情况下,转换基于目标对象坐标系的原点 (0,0) 居中。 唯一例外是 TranslateTransform;由于其转换效果无论基于何处居中都相同,因此 TranslateTransform 没有可设置的中心属性。
以下示例使用 RotateTransform 围绕默认中心点 (0, 0) 将 Rectangle 元素(一种 FrameworkElement)旋转 45 度。 下图显示了旋转效果。
围绕点 (0,0) 旋转 45 度的矩形元素
<Canvas Width="200" Height="200">
<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
默认情况下,元素会围绕其左上角 (0, 0) 旋转。 RotateTransform、ScaleTransform 和 SkewTransform 类提供 CenterX 和 CenterY 属性,以便可以指定应用转换的点。
下面的示例也使用 RotateTransform 将 Rectangle 元素旋转 45 度;但是,这次对 CenterX 和 CenterY 属性进行了设置,使得 RotateTransform 以 (25, 25) 为中心。 下图显示了旋转效果。
围绕点 (25, 25) 旋转 45 度矩形元素
<Canvas Width="200" Height="200">
<Rectangle
Canvas.Left="100" Canvas.Top="100"
Width="50" Height="50"
Fill="RoyalBlue" Opacity="1.0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="25" CenterY="25" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
转换 FrameworkElement
若要将转换应用到 FrameworkElement,请创建 Transform 并将其应用到 FrameworkElement 类所提供的两个属性之一:
LayoutTransform - 在布局步骤前应用的转换。 转换应用后,布局系统处理元素转换后的大小和位置。
RenderTransform - 修改元素外观的转换,但在布局步骤完成后应用。 使用 RenderTransform 属性(而非 LayoutTransform 属性),可获得性能优势。
应使用哪个属性? 由于 RenderTransform 属性提供性能优势,因此尽可能使用该属性,特别是使用经动画处理后的 Transform 对象时。 在进行缩放、旋转或倾斜,并且需要父级元素来对元素转换后的大小进行调整时,可使用 LayoutTransform 属性。 注意,在与 LayoutTransform 属性一起使用时,TranslateTransform 对象应该对元素没有影响。 这是因为布局系统将转换后的元素返回到其原始位置作为其处理的一部分。
有关 Windows Presentation Foundation (WPF) 中的布局的其他信息,请参阅布局概述。
示例:将 FrameworkElement 旋转 45 度
下面的示例使用 RotateTransform 将按钮顺时针旋转 45 度。 按钮包含在 StackPanel 中,其他两个按钮也包含在其中。
默认情况下,RotateTransform 围绕点 (0, 0) 旋转。 由于示例未指定中心点值,按钮将围绕点 (0, 0) 旋转,即其左上角。 RotateTransform 应用于 RenderTransform 属性。 下图显示转换的结果。
从左上角顺时针旋转 45 度
<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1" >
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>
下面的示例也使用 RotateTransform 将按钮顺时针旋转 45 度,但它还将按钮的 RenderTransformOrigin 设置为 (0.5, 0.5)。 RenderTransformOrigin 属性值与按钮的大小有关。 因此,该旋转应用到按钮的中心,而非左上角。 下图显示转换的结果。
围绕中心顺时针旋转 45 度
<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>
下面的示例使用 LayoutTransform 属性而不是 RenderTransform 属性来旋转按钮。 这将导致转换影响按钮的布局,从而触发布局系统的整个处理过程。 因此,按钮在旋转后重新定位,因为它的大小已更改。 下图显示转换的结果。
用于旋转按钮的 LayoutTransform
<Border Margin="30"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Button Content="A Button" Opacity="1" />
<Button Content="Rotated Button">
<Button.LayoutTransform>
<RotateTransform Angle="45" />
</Button.LayoutTransform>
</Button>
<Button Content="A Button" Opacity="1" />
</StackPanel>
</Border>
对转换进行动画处理
因为它们继承自 Animatable 类,所以 Transform 类可以被制作成动画。 若要对 Transform 进行动画处理,请将兼容类型的动画应用到要进行动画处理的属性。
下面的示例使用 Storyboard、DoubleAnimation 和 RotateTransform使 Button 在单击时就地旋转。
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Button Animated RotateTransform Example"
Background="White" Margin="50">
<StackPanel>
<Button Content="A Button"
RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<RotateTransform x:Name="AnimatedRotateTransform" Angle="0" />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="AnimatedRotateTransform"
Storyboard.TargetProperty="Angle"
To="360" Duration="0:0:1" FillBehavior="Stop" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Page>
有关完整示例,请参阅 2D 转换示例。 有关动画的详细信息,请参阅动画概述。
Freezable 功能
由于继承自 Freezable 类,Transform 类提供多种特殊功能:Transform 对象可以声明为 资源、在多个对象之间共享、变为只读以提高性能、克隆以及变为线程安全。 有关 Freezable 对象所提供的不同功能的详细信息,请参阅 Freezable 对象概述。