【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. 简 ...
随机推荐
- 「算法竞赛进阶指南」0x01 位运算 知识笔记
二进制是计算机的根本! 你了解她它吗? int lowbit(int x) { return x&(-x);//x&(~x+1),~x=-1-x; } int __builtin_ct ...
- 08_jquery里面的$(this)和this都什么时候用,有什么区别
当你用的是jquery时,就用$(this),如果是JS,就用this $(this).html( $(this).html() + " BAM! "); 这个里的html()是J ...
- vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
一.思路分析和效果图 用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果.然后针对这几个效果的实现,捋下思路: 根据加载数据的顺序,依次追加标签展示效果: 选择哪种方式实 ...
- Linux查看端口监听占用
# 查看所有 netstat -ntlp # 过滤PORT8080 netstat -ntlp | grep 8080 -t # 仅显示tcp相关选项 -u # 仅显示udp相关选项 -n # 拒绝显 ...
- cf 697C Lorenzo Von Matterhorn 思维
题目链接:https://codeforces.com/problemset/problem/697/C 两种操作: 1是对树上u,v之间的所有边的权值加上w 2是查询树上u,v之间的边权和 树是满二 ...
- 2、Automapper安装及配置
一. 安装 我们安装是在 vs 中使用Nuget的方式进行安装 不过安装时需注意一件事情就是,版本问题,我示例使用的是.net framework 4.5.2,所以我安装AutoMapper的版本是7 ...
- 让现有vue前端项目快速支持多语言 - 用.net core程序快速替换中文为资源Key,咱不干体力活
前言 最近应公司上层要求,需要将现有项目尽快支持多语言,而中文内容可以找专业人员翻译.那么咱们说干就干,首先我们项目的前端是用vue写的spa程序且组件方面用的element ui,那么自然而然想到用 ...
- 7.Arrays数组的工具类
Arrays类: 数组的工具类java.util.Arrays 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作. ...
- fastjson中Map与JSONObject互换
1.//将map转换成jsonObject JSONObject itemJSONObj = JSONObject.parseObject(JSON.toJSONString(itemMap)); 将 ...
- Tensorflow下指定显卡占用比例参数配置
tensorflow在训练时默认占用所有GPU的显存. 可以通过以下方式解决该问题: 1.在构造tf.Session()时候通过传递tf.GPUOptions作为可选配置参数的一部分来显式地指定需要分 ...