WPF中的变换(Transform)功能详解 - 实践
Transform
在WPF中,我们可以通过变换(Transform),对UI对象进行旋转、缩放、移动(平移)和倾斜等操作
通过使用变换(transform),许多绘图任务将更趋简单;
在 WPF 中,变换由继承自System.Windows.Media.Transform抽象类的类表示,
常用的Transform派生类如下所示
| 类型 | 描述 | 常用属性 | 示意图 |
|---|---|---|---|
| RotateTransform | 旋转坐标系统。正常绘制的形状绕着选择的中心点旋转 | Angle:角度 CenterX:旋转中心坐标-X CenterY:旋转中心坐标-Y |
|
| ScaleTransform | 放大或缩小坐标系统,从而绘制更大或更小的图形。 可在X和Y方向应用不同的缩放度,从而拉伸或压缩形状 | ScaleX:X方向的缩放度 ScaleY:Y方向的缩放度 CenterX:缩放中心坐标-X CenterY:缩放中心坐标-Y |
|
| SkewTransform | 通过倾斜一定的角度扭曲坐标系统。 例如,如果绘制正方形,通过该变换正方形会变成平行四边形 | AngleX:X方向的倾斜度 AngleY:Y方向的倾斜度 CenterX:倾斜中心坐标-X CenterY:倾斜中心坐标-Y |
|
| TranslateTransform | 将坐标系统移动一定距离。 | X:X方向偏移距离 Y:Y方向偏移距离 |
|
另外还有两种复杂一点的派生类型
| 类型 | 描述 |
|---|---|
| TransformGroup | 组合多个变换,从而可以一次应用所有这些变换。应用变换的顺序是很重要的,因为这会影响最终结果。 例如,首先使用RotateTransform旋转形状,然后使用TranslateTransform移动形状,这样做的结果和先移动再旋转的结果是不同的 |
| MatrixTransform | 使用提供的矩阵的乘积修改坐标系统。这是最复杂的选择——为实现该变换,需要掌握一些数学技巧 |
Transform的原理
从技术角度看,所有变换都使用矩阵数学改变形状的坐标。不过,使用预先构建好的变换,如TranslateTransform 、 RotateTransform、ScaleTransform以及SkewTransform ,
比使用MatrixTransform并尝试为希望执行的操作构造正确的矩阵要简单得多。
底层调用来说,都是使用了MILCMD_MATRIXTRANSFORM类型作为最终传递的数据结构
1 [StructLayout(LayoutKind.Explicit, Pack=1)]
2 internal struct MILCMD_MATRIXTRANSFORM
3 {
4 [FieldOffset(0)] internal MILCMD Type;
5 [FieldOffset(4)] internal DUCE.ResourceHandle Handle;
6 [FieldOffset(8)] internal MilMatrix3x2D Matrix;
7 [FieldOffset(56)] internal DUCE.ResourceHandle hMatrixAnimations;
8 };
当使用TransformGroup执行一系列变换时,WPF将所有变换融合到单独的MatrixTransform变换中以确保获得最佳性能。
在win32编程或winform中,没有提供类似的变换功能,需要我们进行重绘才能实现。
简而言之,就是为了方便用户使用,RotateTransform、ScaleTransform等类型是对MatrixTransform类型进行了再封装。
变换元素(Transforming a FrameworkElement)
这里分为了两种类型
LayoutTransform – 在布局过程开始前应用的变换。 应用转换后,布局系统将处理元素的转换大小和位置。
RenderTransform – 修改元素外观的转换,但在布局处理完成后应用。 通过使用属性 RenderTransform 而不是 LayoutTransform 属性,可以获得性能优势。
这两种类型的应用场景:
尽可能使用 RenderTransform 属性,尤其是在使用动画 Transform 对象时。
如果需要元素在进行缩放、旋转或倾斜时,父级调整为元素变换后的大小,可以使用LayoutTransform属性,
下面我们来演示一下
我们在界面上放置一个Image控件,然后来看一下当使用不同Transform时,它呈现的效果。
1
2
3
4
5
6
RotateTransform
1
2
3
4
5
6
7
8
9
10
11
12
ScaleTransform
1
2
3
4
5
6
7
8
9
10
11
12
SkewTransform
1
2
3
4
5
6
7
8
9
10
11
12
TranslateTransform
1
2
3
4
5
7
8
9
10
11
12
TransformGroup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MatrixTransform
1
2
3
4
5
6
7
8
9
10
11
12
13
14
关于MatrixTransform,本文没有做详细介绍,可以参考下面的链接
运行结果:

转换和坐标系统
在对WPF中的对象进行转换(Transform)时,不仅仅是转换了这个对象,而且还包括了该对象所在的坐标空间。
默认情况下,转换以目标对象的坐标系的原点为中心:(0,0)
使用RotateTransform 的 CenterX和 CenterY属性时存在明显的限制。
这些属性是使用绝对坐标定义的,也就是说我们需要知道内容的中心点的准确位置。
如果正在显示动态内容(例如,可变维度的图片或可改变尺寸的元素),就会出现问题。
这个时候我们可以通过UIElement.RenderTransformOrigin属性使用相对坐标系统设置中心点。相对坐标系统在两个方向上的范围都是从0到1。
换句话说,点(0,0)被指定为左上角,点(1,1)表示右下角(如果形状区域不是正方形,那么会相应地拉伸坐标系统)。
借助于RenderTransformOrigin属性,可使用如下所示的代码,绕中心点旋转任意元素:
1
2
3
4
5
6
7
8
9
10
注意:在WPF中只有少量元素不能使用Transform,例如WindowsFormHost和WebView2
示例代码
参考资料:
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/transforms-overview




浙公网安备 33010602011771号