了解如何通过在 UI 中更改元素的相对坐标系,在 Windows 运行时 API 中使用转换。 这可用于调整单个 XAML 元素的外观,例如缩放、旋转或转换 x-y 空间中的位置。
什么是转换?
转换 定义如何映射或转换从一个坐标空间到另一个坐标空间的点。 将转换应用于 UI 元素时,它会更改 UI 元素作为 UI 的一部分呈现到屏幕的方式。
考虑四种广泛的分类中的变换:平移、旋转、缩放和倾斜(亦称剪切)。 为了使用图形API更改UI元素的外观,通常最简单的方法是创建每次只定义一个操作的转换。 因此,Windows 运行时为每个转换分类定义一个离散类:
- TranslateTransform:通过设置 X 和Y 的值来转换 x-y 空间中的元素。
- ScaleTransform:通过设置 CenterX、CenterY、ScaleX 和 ScaleY的值,以基于中心点缩放转换。
- RotateTransform:在 x-y 空间中通过设定 角度、CenterX 和 CenterY的值来旋转。
- SkewTransform:通过设置 AngleX、AngleY、CenterX 和 CenterY的值,在 x-y 空间中设置倾斜或剪切。
其中,你可能最常将 TranslateTransform 和 ScaleTransform 用于 UI 方案。
可以合并转换,并且有两个 Windows 运行时类支持此目的: CompositeTransform 和 TransformGroup。 在 CompositeTransform中,按以下顺序应用转换:缩放、倾斜、旋转、转换。 如果希望以不同的顺序应用转换,请使用 TransformGroup 而不是 CompositeTransform。 更多信息,请参阅 CompositeTransform。
转换和布局
在 XAML 布局中,转换在布局过程完成后应用,因此即在应用转换之前已做出可用空间的计算和其他布局决策。 由于布局优先,如果您对位于 网格 单元或在布局期间分配空间的类似布局容器中的元素进行转换,有时会出现意外的结果。 转换后的元素可能显示为截断或遮盖,因为它试图绘制到在父容器内划分空间时未计算转换后维度的区域。 可能需要试验转换结果并调整某些设置。 例如,不要依赖自适应布局和星型调整,可能需要更改 中心 属性或声明布局空间的固定像素度量,以确保父级分配足够的空间。
迁移说明: Windows Presentation Foundation(WPF)具有 LayoutTransform 属性,该属性在布局过程之前应用转换。 但 Windows 运行时 XAML 不支持 LayoutTransform 属性。 (Microsoft Silverlight 也没有此属性。
作为替代方法,Windows 社区工具包提供了 LayoutTransformControl,可以对应用程序的任何 FrameworkElement 应用矩阵变换。
将变换应用到 UI 元素
将转换应用于对象时,通常可以设置属性 UIElement.RenderTransform。 设置此属性并不会逐个像素更改对象。 该属性的真正功能是在该对象存在的本地坐标空间中应用变换。 然后,渲染逻辑和操作(后布局)渲染组合坐标空间,使其看起来像对象改变了外观,也可能改变了布局位置(如果应用了 TranslateTransform)。
默认情况下,每个呈现转换都以目标对象的本地坐标系(0,0)的原点居中。 唯一的例外是TranslateTransform,它没有要设置的中心属性,因为平移效果是相同的,无论其中心在哪里。 但每个其他转换都具有用于设置 CenterX 和 CenterY 的属性。
每当对 UIElement.RenderTransform使用转换时,请记住,UIElement 上有另一个属性,会影响转换的效果:RenderTransformOrigin。 RenderTransformOrigin 声明的
出于命中测试目的,应用转换的对象继续以符合 x-y 空间中的视觉外观的预期方式响应输入。 例如,如果使用 TranslateTransform 在 UI 中横向移动 矩形 400 像素,当用户按下 矩形 的位置时,矩形 将响应 PointerPressed 事件。 如果用户在 矩形 平移之前按下其所在区域,则不会收到错误事件。 对于影响命中测试的任何 z 索引注意事项,应用变换不会产生任何影响;决定哪个元素处理在 x-y 空间中某个点的输入事件的 z 索引仍然根据容器中声明的子元素顺序进行评估。 该顺序通常与在 XAML 中声明元素的顺序相同,尽管对于 Canvas 对象的子元素,可以通过将 Canvas.ZIndex 附加属性应用于子元素来调整顺序。
其他转换属性
- Brush.Transform,Brush.RelativeTransform:这些影响 画笔 在用于设置前景和背景等视觉属性的 画笔 的应用区域内的坐标空间的使用方式。 这些转换与最常见的画笔(通常使用 SolidColorBrush 设置纯色)无关,但在使用 ImageBrush 或 LinearGradientBrush 绘制区域时可能偶尔有用。
- Geometry.Transform:在对 Path.Data 属性值使用该几何图形之前,可以使用此属性将转换应用于几何图形。
对转换进行动画处理
转换 对象可以进行动画处理。 若要对 转换进行动画处理,请将兼容类型的动画应用于要进行动画处理的属性。 这通常意味着使用 DoubleAnimation 或 DoubleAnimationUsingKeyFrames 对象来定义动画,因为所有变换属性都是 Double类型。 影响用于 UIElement.RenderTransform 值的转换的动画不被视为依赖动画,即使它们具有非零持续时间。 关于依赖动画的更多信息,请参阅 分镜动画。
如果对属性进行动画处理,以在净视觉外观方面生成类似于转换的效果(例如,对 Width 和 Height 进行动画处理,FrameworkElement 而不是应用 TranslateTransform),则此类动画几乎始终被视为依赖动画。 必须启用动画,并且动画可能存在显著的性能问题,尤其是在尝试在对象进行动画处理时支持用户交互时。 因此,最好使用转换并对其进行动画处理,而不是对动画视为依赖动画的任何其他属性进行动画处理。
若要以转换为目标,必须存在现有的 转换 作为 RenderTransform的值。 通常,在初始 XAML 中为适当的转换类型放置一个元素,有时该转换上未设置任何属性。
通常使用间接定位方法将动画应用于变换的属性。 有关间接目标语法的详细信息,请参阅 情节提要动画 和 属性路径语法。
控件的默认样式有时将变换的动画定义为其视觉状态行为的一部分。 例如,ProgressRing 的视觉状态使用动画 RotateTransform 值来“旋转”圈中的点。
下面是有关如何对转换进行动画处理的简单示例。 在本例中,它正在对 RotateTransform 的 Angle 进行动画处理,使 矩形 围绕其视觉中心原地旋转。 本示例将 RotateTransform 命名,因此不需要采用间接动画定位。不过,您也可以将转换保持未命名状态,命名应用转换的元素,然后使用间接定位,例如 (UIElement.RenderTransform).(RotateTransform.Angle)
。
<StackPanel Margin="15">
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimation
Storyboard.TargetName="myTransform"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:5"
RepeatBehavior="Forever" />
</Storyboard>
</StackPanel.Resources>
<Rectangle Width="50" Height="50" Fill="RoyalBlue"
PointerPressed="StartAnimation">
<Rectangle.RenderTransform>
<RotateTransform x:Name="myTransform" Angle="45" CenterX="25" CenterY="25" />
</Rectangle.RenderTransform>
</Rectangle>
</StackPanel>
void StartAnimation (object sender, RoutedEventArgs e) {
myStoryboard.Begin();
}
在运行时对参考坐标系进行考虑
UIElement 具有一个名为 TransformToVisual的方法,该方法可以生成一个 Transform,用于将两个 UI 元素的坐标参考框架关联起来。 如果将根视觉对象作为第一个参数传递,则可以使用它将元素与应用的默认引用坐标帧进行比较。 如果已从其他元素捕获输入事件,或者尝试预测布局行为而不实际请求布局传递,这非常有用。
从指针事件获取的事件数据提供访问权限,通过 GetCurrentPoint 方法,您可以指定 relativeTo 参数,以将坐标参考框架更改为特定元素,而不是应用的默认值。 此方法仅仅需要在内部应用平移变换,并在为你创建返回 PointerPoint 对象时转换 x-y 坐标数据。
以数学方式描述转换
可以在转换矩阵中描述转换。 3×3 矩阵用于描述二维 x-y 平面中的转换。 仿射变换矩阵可以相乘以实现任意数量的线性变换,如旋转和剪切,接着是平移。 相交转换矩阵的最后一列等于 (0, 0, 1),因此只需在数学说明中指定前两列的成员。
如果你有数学背景或熟悉图形编程技术,则转换的数学说明可能对你有用,这些技术也使用矩阵来描述坐标空间的转换。 有一个 变换派生类,使您能够通过其 3×3 矩阵直接表示变换:MatrixTransform。 MatrixTransform 有一个 Matrix 属性,该属性包含一个具有六个属性的结构: M11、 M12、 M21、 M22、 OffsetX 和 OffsetY。 每个 矩阵 属性都使用 Double 值,对应于相交转换矩阵的六个相关值(第 1 列和第 2 列)。
列 1 | 第 2 列 | 列 3 |
---|---|---|
M11 | M12 | 0 |
M21 | M22 | 0 |
OffsetX | OffsetY | 1 |
可以用 TranslateTransform、ScaleTransform、RotateTransform或 SkewTransform 对象描述的任何转换,也可以通过具有 矩阵 值的 MatrixTransform 来描述。 但通常只需使用 TranslateTransform 和其他人,因为这些转换类的属性比在 矩阵中设置向量组件更容易概念化。 还可以更轻松地对变换的离散属性进行动画处理; 矩阵 实际上是一个结构,而不是 DependencyObject,因此它不支持各个值的动画。
一些可用于应用转换作的 XAML 设计工具会将结果序列化为 MatrixTransform。 在这种情况下,最好再次使用相同的设计工具来修改转换效果并再次序列化 XAML,而不是尝试直接在 XAML 中操作 矩阵 值。
三维转换
在 Windows 10 中,XAML 引入了一个新属性 UIElement.Transform3D,可用于使用 UI 创建 3D 效果。 为此,请使用 PerspectiveTransform3D 将共享的 3D 透视或“相机”添加到场景中,然后使用 CompositeTransform3D 来转换 3D 空间中的元素,就像您会使用 CompositeTransform 一样。 有关如何实现 3D 转换的讨论,请参阅 UIElement.Transform3D 。
对于仅适用于单个对象的更简单的 3D 效果,可以使用 UIElement.Projection 属性。 使用 PlaneProjection 作为此属性的值,相当于对元素应用固定透视变换和一个或多个 3D 变换。 XAML UI的三维透视效果中更详细地描述了这种类型的转换。