【WPF学习】第四十一章 变换
通过使用变换(transform),许多绘图任务将更趋简单;变换是通过不加通告地切换形状或元素使用的坐标系统来改变形状或元素绘制方式的对象。在WPF中,变换由继承自System.Windows.Media.Transform抽象类的类表示。下表列出了这些类。
表 变换类
从技术角度看,所有变换都使用矩阵数学改变形状的坐标。不过,使用预先构建好的变换,如TranslateTransform、RotateTransform、ScaleTransform以及SkewTransform,比使用MatrixTransform并尝试为希望执行的操作构造正确的矩阵更简单的多。当使用TransformGroup执行一系列变换时,WPF将所有变换融合到单独的MatrixTransform变换中以确保获得最佳性能。
所有变换(通过Transform类)继承自Freezable类,这意味着它们支持自动更改通知功能。如果改变了在形状中使用的变换,形状会立即重新绘制自身。
变换是那些在不同上下文中非常有用的古怪概念中的一个。下面例举几个例子:
- 倾斜形状。到目前为止已经介绍了水平对齐的矩形、椭圆、直线以及多边形。使用RotateTransform变换,可转动坐标系统,使创建特定的形状更容易。
- 重复形状。许多图画是在不同的位置使用类似的形状构建的。使用变换,可先绘制一个形状,然后移动、旋转、缩放该形状,以及执行其他操作。
- 动画。通过变换,可创建大量精致的效果。例如,旋转形状、将形状从一个地方移到另一个地方,以及动态扭曲形状。
一、变换形状
为变换形状,将RenderTransform属性指定为希望使用的变换队形。根据使用的变换队形,需要填充不同的属性以配置变换队形。
例如,如果旋转形状,需要使用RotateTransform变换,并以度为单位提供旋转角度。下面的示例将举行旋转25°:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle>
采用这种方式旋转形状时,是围绕形状的原点进行旋转的(左上角)。下图演示了绕形状原点旋转25°、50°、75°以及100°的效果。
<Window x:Class="Drawing.RotateShape"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateShape" Height="427" Width="332"
>
<Canvas>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="50" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="100" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas> </Window>
RotateShape
有时候希望绕不同的点旋转形状。与其他许多变换类一样,RotateTransform变换也提供了CenterX和CentertY属性。可以用这些属性指定将进行旋转的中心。下面的矩形使用该方法绕其中心点旋转自身25°:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
采用这种方式旋转形状时,是围绕形状的原点进行旋转的(中心)。下图演示了绕形状原点旋转25°、50°、75°以及100°的效果。
<Window x:Class="Drawing.RotateShape"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateShape" Height="427" Width="332"
>
<Canvas>
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="50" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle> <Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300">
<Rectangle.RenderTransform>
<RotateTransform Angle="100" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas> </Window>
RotateShape
使用RotateTransform的CenterX和CenterY属性时存在明显的限制。这些属性是使用绝对坐标定义的,这意味着需要了解绘制内容的中心店的准确位置。如果正在显示动态内容(例如,可变维度的图片或改变尺寸的元素),就会出现问题。幸运的是,WPF通过方便的RenderTransformOrigin属性,为这个问题提供了解决方法,所以形状都支持RenderTransformOrign属性。该属性使用相对坐标系统设置中心点,下该对坐标系统在两个方向上的范围都是从0到1。换句话说,点(0,0)被指定为左上角,点(1,1)表示右下角(如果形状区域不是正方形,那么会相应地拉伸坐标系统)。
借助于RenderTransformOrigin属性,可使用如下所示的标记,绕中心点旋转任意形状:
<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="300" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="75" CenterX="45" CenterY="5" />
</Rectangle.RenderTransform>
</Rectangle>
因为不管形状的尺寸是多少,点(0.5,0.5)都表示形状中心,所以上面的标记可以工作。实际上,RenderTransformOrigin属性通常比CenterX和CenterY属性更有用,尽管根据需要可以使用两者中的一个,或者同时使用两者。
二、变换元素
RenderTransform和RenderTransformOrigin属性并不限制只能用于形状。实际上,Shape类的这些属性从UIElement类继承而来,这意味着所有WPF元素都支持这两个属性,包括按钮、文本框、TextBlock控件、充满内容的整个布局容器等。令人感到惊讶的是,可旋转、扭曲以及缩放WPF用户界面中的任意一部分。
RenderTransform不是在WPF基类中定义的唯一与变换相关的属性。FrameworkElement类还定义了LayoutTransform属性。LayoutTransform属性以相同的方式变换元素,但在布局之前执行其工作。这种情况的开销虽然更大些,但如果使用布局容器为一组控件提供自动布局功能,这种方式是很关键的(Shape类也提供了LayoutTransform属性,但很少需要使用该属性,因此通常使用容器(如Canvas面板)明确地放置形状,而不是使用自动布局)。
为理解两者的区别,分析下图中显示的窗口,该窗口包含两个StackPanel容器(由阴影区域表示),这两个容器都包含一个选择过的按钮和一个正常的按钮。在第一个StackPanel容器中,选择的按钮使用RenderTransform方法。该StackPanel容器在对两个按钮进行布局时,第一个按钮正常定位,并且在即将呈现之前旋转该按钮。因此,选择过的按钮被重叠在下面。在第二个StackPanel容器中,选择过的按钮使用LayoutTransform方法。StackPanel容器获取到选项后按钮所需的边界,并相应地布局第二个按钮。
<Window x:Class="Drawing.RotateElement"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="RotateElement" Height="314" Width="305"
>
<StackPanel>
<StackPanel Margin="25" Background="LightYellow">
<Button Padding="5" HorizontalAlignment="Left">
<Button.RenderTransform>
<RotateTransform Angle="35" CenterX="45" CenterY="5" />
</Button.RenderTransform>
<Button.Content>I'm rotated 35 degrees</Button.Content>
</Button>
<Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
</StackPanel> <StackPanel Margin="25" Background="LightYellow">
<Button Padding="5" HorizontalAlignment="Left">
<Button.LayoutTransform>
<RotateTransform Angle="35" CenterX="45" CenterY="5" />
</Button.LayoutTransform>
<Button.Content>I'm rotated 35 degrees</Button.Content>
</Button>
<Button Padding="5" HorizontalAlignment="Left">I'm not</Button>
</StackPanel>
</StackPanel>
</Window>
RotateElement
只有很少几个元素不能被变换,因为他们的呈现工作并非由WPF本身负责。不能被变换的元素的两个例子是WindowsFormHost和WebBrower元素,WindowsFormHost元素用于在WPF窗口中放置Windows窗体控件,WebBrower元素用于显示HTML内容。
在一定程度上,当设置LayoutTransform或RenderTransform属性时,WPF元素不知道它们正在被修改。特别是,变换不会影响元素的ActualHeight和ActualWidth属性,它们仍记录着变换之前的值。这正是WPF能够保证流失布局以及外边距继续以相同的方式工作的部分原理,即使应用了一个或多个变换也同样如此。
【WPF学习】第四十一章 变换的更多相关文章
- 【WPF学习】第五十三章 动画类型回顾
创建动画面临的第一个挑战是为动画选择正确的属性.期望的结果(例如,在窗口中移动元素)与需要使用的属性(在这种情况下是Canvas.Left和Canvas.Top属性)之间的关系并不总是很直观.下面是一 ...
- 【WPF学习】第二十六章 Application类——应用程序的生命周期
在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一 ...
- 【WPF学习】第五十四章 关键帧动画
到目前为止,看到的所有动画都使用线性插值从起点到终点.但如果需要创建具有多个分段的动画和不规则移动的动画.例如,可能希望创建一个动画,快速地将一个元素滑入到视图中,然后慢慢地将它移到正确位置.可通过创 ...
- 【WPF学习】第五十七章 使用代码创建故事板
在“[WPF学习]第五十章 故事板”中讨论了如何使用代码创建简单动画,以及如何使用XAML标记构建更复杂的故事板——具有多个动画以及播放控制功能.但有时采用更复杂的故事板例程,并在代码中实现全部复杂功 ...
- 【WPF学习】第五十章 故事板
正如上一章介绍,WPF动画通过一组动画类(Animation类)表示.使用少数几个熟悉设置相关信息,如开始值.结束值以及持续时间.这显然使得它们非常适合于XAML.不是很清晰的时:如何为特定的事件和属 ...
- WPF学习05:2D绘图 使用Transform进行控件变形
在WPF学习04:2D绘图 使用Shape绘基本图形中,我们了解了如何绘制基本的图形. 这一次,我们进一步,研究如何将图形变形. 例子 一个三角形,经Transform形成组合图形: XAML代码: ...
- WPF学习:3.Border & Brush
上一章<WPF学习:2.Layout-Panels-Countainers>主要介绍了布局,容器和面板.这一章主要开始介绍Border(边界)和Brush(画刷). 代码地址:http:/ ...
- “全栈2019”Java第四十一章:static关键字
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- Asp.Net MVC4 + Oracle + EasyUI 学习 序章
Asp.Net MVC4 + Oracle + EasyUI 序章 -- 新建微软实例 本文链接:http://www.cnblogs.com/likeli/p/4233387.html 1. 简 ...
随机推荐
- Python基础复习函数篇
目录 1.猴子补丁2. global和nonlocal关键字3.迭代器和生成器4.递归函数5.高阶函数和lamdba函数6.闭包7.装饰器 1. 猴子补丁 猴子补丁主要用于在不修改已有代码情况下修 ...
- java数据结构之常用排序算法
冒泡排序 private void maopao(int arr[]) { for (int i = 0; i < arr.length; i++) { for (int j = 0; j &l ...
- docker-bind挂载
使用绑定挂载 自Docker早期以来,绑定挂载一直存在.与卷相比,绑定装载具有有限的功能.使用绑定装入时,主机上的文件或目录将装入容器中.文件或目录由其在主机上的完整路径或相对路径引用.相反,当您使用 ...
- Kubernetes 会不会“杀死” DevOps?
作者丨孙健波(天元) 阿里巴巴技术专家 导读:DevOps 这个概念最早是在 2007 年提出的,那时云计算基础设施的概念也才刚刚提出没多久,而随着互联网的逐渐普及,应用软件的需求爆发式增长,软件开 ...
- iFit—Smart Cardio Equipment 简介与下载
iFit—Smart Cardio Equipment 无法在谷歌商店中下载,经过技术提取app只可以直接通过下载app安装简单方便 实测机型:华为荣耀畅玩2平板, 小米6X,360N5S均测试无BU ...
- java小项目之:植物大战僵尸,这个僵尸有点冷!内附素材源码
Java小项目之:植物大战僵尸! <植物大战僵尸>是由PopCap Games开发的一款益智策略类单机游戏,于2009年5月5日发售,这款游戏可谓是无人不知无人不晓. 在我身边,上到40岁 ...
- Java面向对象之异常【一】
目录 Java面向对象之异常[一] 异常的继承体系 Error Exception 异常是否受检 unchecked exceptions(不受检异常) checked exceptions(受检异常 ...
- .Net Core - AgileHttp
2020年新年将至,先预祝.Net Core越来越好. 做了这么多年一线开发,经常跟Http打交道.比如调用三方的Webservice,比如集成微信支付的时候服务端发起Prepay支付.特别是现在分布 ...
- TensorFlow——TensorBoard可视化
TensorFlow提供了一个可视化工具TensorBoard,它能够将训练过程中的各种绘制数据进行展示出来,包括标量,图片,音频,计算图,数据分布,直方图等,通过网页来观察模型的结构和训练过程中各个 ...
- 你还不会Git?那就不要写代码了(一)
Git应用开发学习 如果你还不会使用Git,那就不要写代码了. 一旦你会使用了Git,就再也不想使用SVN了.永远也回不去了. Mac上使用Git,肯定离不开对Mac上的操作.就要使用常用的Linux ...