通过使用变换(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学习】第四十一章 变换的更多相关文章

  1. 【WPF学习】第五十三章 动画类型回顾

    创建动画面临的第一个挑战是为动画选择正确的属性.期望的结果(例如,在窗口中移动元素)与需要使用的属性(在这种情况下是Canvas.Left和Canvas.Top属性)之间的关系并不总是很直观.下面是一 ...

  2. 【WPF学习】第二十六章 Application类——应用程序的生命周期

    在WPF中,应用程序会经历简单的生命周期.在应用程序启动后,将立即创建应用程序对象,在应用程序运行时触发各种应用程序事件,你可以选择监视其中的某些事件.最后,当释放应用程序对象时,应用程序将结束. 一 ...

  3. 【WPF学习】第五十四章 关键帧动画

    到目前为止,看到的所有动画都使用线性插值从起点到终点.但如果需要创建具有多个分段的动画和不规则移动的动画.例如,可能希望创建一个动画,快速地将一个元素滑入到视图中,然后慢慢地将它移到正确位置.可通过创 ...

  4. 【WPF学习】第五十七章 使用代码创建故事板

    在“[WPF学习]第五十章 故事板”中讨论了如何使用代码创建简单动画,以及如何使用XAML标记构建更复杂的故事板——具有多个动画以及播放控制功能.但有时采用更复杂的故事板例程,并在代码中实现全部复杂功 ...

  5. 【WPF学习】第五十章 故事板

    正如上一章介绍,WPF动画通过一组动画类(Animation类)表示.使用少数几个熟悉设置相关信息,如开始值.结束值以及持续时间.这显然使得它们非常适合于XAML.不是很清晰的时:如何为特定的事件和属 ...

  6. WPF学习05:2D绘图 使用Transform进行控件变形

    在WPF学习04:2D绘图 使用Shape绘基本图形中,我们了解了如何绘制基本的图形. 这一次,我们进一步,研究如何将图形变形. 例子 一个三角形,经Transform形成组合图形: XAML代码: ...

  7. WPF学习:3.Border & Brush

    上一章<WPF学习:2.Layout-Panels-Countainers>主要介绍了布局,容器和面板.这一章主要开始介绍Border(边界)和Brush(画刷). 代码地址:http:/ ...

  8. “全栈2019”Java第四十一章:static关键字

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. Asp.Net MVC4 + Oracle + EasyUI 学习 序章

    Asp.Net MVC4 + Oracle + EasyUI  序章 -- 新建微软实例 本文链接:http://www.cnblogs.com/likeli/p/4233387.html 1.  简 ...

随机推荐

  1. day2(使用list和tuple)

    list list是一种有序的集合 >>>aaa = ['abc','bob','tracy'] >>>aaa ['abc','bob','tracy'] len( ...

  2. 前端Tips#3 - 简写的 border-radius 100% 和 50% 是等效的

    本文同步自 JSCON简时空 - 技术博客,点击阅读 视频讲解 视频地址 文字讲解 1.先讲结论 border-radius 这个 css 属性大家应该使用得非常娴熟,现实中用到的场景基本都是四个圆角 ...

  3. ACM北大暑期课培训第八天

    今天学了有流量下界的网络最大流,最小费用最大流,计算几何. 有流量下界的网络最大流 如果流网络中每条边e对应两个数字B(e)和C(e), 分别表示该边上的流量至少要是B(e),最多 C(e),那么,在 ...

  4. CTO说|非容器化应用怎么玩多云?Kubernetes不管我们管啊

    Kubernetes已经成为容器编排系统的事实标准,是现在主流的跨云容器化应用操作系统. 但是,Kubernetes的目标并不是容器本身,而是承载其上的应用,本质上是为了解决(容器化)应用上云这个难题 ...

  5. Maven 基础(一) | 使用 Maven 的正确姿势

    一.什么是 Maven? Maven 是一个项目管理工具,它的本质是一个项目对象模型(POM),体现在配置中就是我们常见的 pom.xml 文件,而这个 pom 文件就是 Maven 的核心,它管理了 ...

  6. cogs 182. [USACO Jan07] 均衡队形 线段树

    182. [USACO Jan07] 均衡队形 ★★☆   输入文件:lineup.in   输出文件:lineup.out   简单对比时间限制:4 s   内存限制:128 MB 题目描述 农夫约 ...

  7. Java框架之Spring02-AOP-动态代理-AspectJ-JdbcTemplate-事务

    AOP 动态代理 代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上. 代理模式的 ...

  8. dp-最长回文串

    博客 : http://blog.csdn.net/hao_zong_yin/article/details/72730732 问题描述: 求一个序列中的最长回文串,这个串可以不连续 , 如  { 1 ...

  9. 《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》-总结

      一.什么是业务中台 概念来自于阿里,介于前台和后台(此后台指的是云计算.数据库.消息队列.缓存等基础服务) 采用共享式架构设计解决以往烟囱式架构设计的资源浪费.重复造轮.试错成本高的问题 阿里的中 ...

  10. Activiti 启动事件(Start Event)

    Activiti 启动事件(Start Event) 作者:Jesai 生活里,没有容易二字,忧伤是一种本能,而微笑是一种能力 版权所有,未经允许,禁止引用.如需引用,请注明出处. 前言: 启动事件是 ...