通过使用变换(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. python专题我对json的日常操作

    一前言 本篇文章将会阐述对json的日常操作,如何读取json文件,将json文件转为字典:如何将字典转为json,将字典写入文件等: 二 josn数据格式简要说明 json对于初学者可以理解是一种数 ...

  2. ArcEngine版本管理(Version)项目总结

    需求: 在ArcGIS项目中,大型的数据库都是使用ArcSDE进行连接管理.使用的数据版本(Version)都是默认版本(sde.default).这样多个人员在编辑的过程中就直接编辑的是默认版本数据 ...

  3. Centos7下创建和管理用户

    centos服务管理主要命令是systemctl,centos7的服务不再放在/etc/init.d/下;而放在/usr/lib/systemd/system下,centos7系统中systemctl ...

  4. TensorFlow——tf.contrib.layers库中的相关API

    在TensorFlow中封装好了一个高级库,tf.contrib.layers库封装了很多的函数,使用这个高级库来开发将会提高效率,卷积函数使用tf.contrib.layers.conv2d,池化函 ...

  5. cogs 2109. [NOIP 2015] 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分

    2109. [NOIP 2015] 运输计划 ★★★☆   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:3 s   内存限制:256 MB [题 ...

  6. 【UEFI】---关于BIOS,EIST和PState&CState和CPU主频变化得关系

    Intel处理器都支持Turbo和EIST,且一般情况下,各家厂商在BIOS中都会设置EIST和PState的开关,那么这些开关与CPU的频率的关系是什么呢?今天对此做个总结: 按照国际惯例,本次梳理 ...

  7. 固定表头的table

    在前端的开发过程中,表格时经常使用的一种展现形式.在我的开发过程中,当数据过多时,最常用的一种方式就是分页,但是有些地方还是需要滚动.通常的table 会随着滚动,导致表头看不见.一下是我找到的一种固 ...

  8. Webpack实战(五):轻松读懂Webpack如何分离样式文件

    在上一篇文章中我给大家分享了预处理器(loader),里面讲到了style-loader 和css-loader,有关样式引入的问题,但是上面的样式文件只是引入到style标签里面,并不是我想要的样式 ...

  9. 【WPF on .NET Core 3.0】 Stylet演示项目 - 简易图书管理系统(4) - 图书列表界面

    在前三章中我们完成了登录窗口, 并掌握了使用Conductor来切换窗口, 但这些其实都是在为我们的系统打基础. 而本章中我们就要开始开发系统的核心功能, 即图书管理功能了. 通过本章, 我们会接触到 ...

  10. 外网主机远程ssh局域网Linux

    最近,公司有台配置极高的主机盒子(i7,32G,512G),组长让我装上kali,平时渗透测试时可以用,其余时间归我了,这么高配置的机器,怎么舍得让它吃灰呢 .所以我就去研究了一下,如何远程访问局域网 ...