WPF中RenderTransform详解
总目录
文章目录
- 总目录
- 一、RenderTransform(渲染变换)
- 1 RenderTransform介绍
- 2 RenderTransformOrigin(中心点)
- 3 RenderTransform 和LayoutTransform
- 二、TranslateTransform(平移)
- 1 TranslateTransform介绍
- 2 基于TranslateTransform的滑动动画
- 三 、RotateTransform(旋转)
- 1 RotateTransform介绍
- 2 CenterX和CenterY
- 3 基于RotateTransform的 加载动画
- 四、ScaleTransform(缩放)
- 1 ScaleTransform介绍
- 2 基于ScaleTransform的放大缩小,翻转和展开的动画
- 1 放大缩小动画
- 2 翻转动画
- 3 展开动画
- 4 扫描效果动画
- 五、SkewTransform(倾斜)
- 1 SkewTransform介绍
- 六、MatrixTranform(矩阵变换)
- 1 MatrixTranform介绍
- 2 使用MatrixTranform 实现平移,旋转,缩放,倾斜
- 七、TransformGroup(变换组)
- 八、其他
- 结语
一、RenderTransform(渲染变换)
1 RenderTransform介绍
<Border Height="100" Width="100" Background="Red" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
WPF提供了下表种的2D Transform 类,用于常见的转换操作
名称 | 描述 | 重要属性 |
---|---|---|
TranslateTranform | 让对象的位置发生水平方向或竖直方向的直线运动 | X、Y |
RotateTranform | 让对象的位置围绕中心发生旋转的运动 | Angle、CenterX、CenterY |
ScaleTranform | 让对象的大小发生变化,放大对象或者缩小对象 | ScaleX、ScaleY、CenterX、CenterY |
SkewTranform | 让对象的按照设置的角度倾斜 | AngleX、AngelY、CenterX、CenterY |
WPF提供了下表中的类,用于创建复杂的转换效果
名称 | 描述 | 重要属性 |
---|---|---|
MatrixTranform | 矩阵变换,包含以上所有的变换效果。 | Matrix |
TransformGroup | 变换组合,可以随意组合上述的各种变换效果,让对象一次应用所有这些变换。 需要注意:应用变换的顺序,因为这会影响最终的变换结果。如:首先使用RotateTranform,然后再使用TranslateTranform,那么就是先旋转控件对象,然后再控件对象。 | – |
2 RenderTransformOrigin(中心点)
默认 RenderTransformOrigin=“0.5,0.5”,下面通过图形理解一下:
以Image控件的RenderTransformOrigin的属性为例: RenderTransformOrigin是一个比例尺寸,X 和Y 的值,范围均是从0到1
3 RenderTransform 和LayoutTransform
可以通过以下两种方式之一向元素应用转换:
- 如果不希望转换影响布局,请使用该元素的 RenderTransform 属性。
- 如果希望转换影响布局,请使用该元素的 LayoutTransform 属性。
二、TranslateTransform(平移)
1 TranslateTransform介绍
TranslateTransform的作用就是让对象的位置发生水平方向或竖直方向的直线运动
上面动图中,只是在项目未运行状态下,在【转换】这一项属性内调整属性值的效果,当我们调整TranslateTransform的X属性和Y属性的时候,会发现控件会在水平方向和竖直方向做直线运动
2 基于TranslateTransform的滑动动画
以上动画主要就是通过修改对象的TranslateTransform 的X属性值,来实现水平移动的动画效果。
上图侧滑栏代码如下:
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<!--【1】首先在资源中定义动画-->
<Storyboard x:Key="SlipOutStoryboard">
<DoubleAnimation Duration="0:0:0.2" To="-100" Storyboard.TargetName="tt" Storyboard.TargetProperty="X"/>
</Storyboard>
<Storyboard x:Key="SlipInStoryboard">
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetName="tt" Storyboard.TargetProperty="X"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<!--【2】然后在触发器中定义触发动画的路由事件-->
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="mainBorder" >
<BeginStoryboard Storyboard="{StaticResource SlipInStoryboard}"></BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="sideBorder" >
<BeginStoryboard Storyboard="{StaticResource SlipOutStoryboard}"></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid Background="LightGreen">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="mainBorder" Height="200" Width="200" Background="Green"></Border>
<Border x:Name="sideBorder" Height="100" Width="100" Background="Red" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="tt" X="0"/>
</TransformGroup>
</Border.RenderTransform>
</Border>
</StackPanel>
</Grid>
</UserControl>
三 、RotateTransform(旋转)
1 RotateTransform介绍
RotateTransform的作用就是让对象的围绕中心发生旋转的运动
- 当我们调整RotateTransform的Angle属性的时候,控件对象会绕控件中心旋转
- 当我们的控件上,具有RenderTransformOrigin(中心点)的属性的时候,是无法设置RotateTransform中的CenterX和CenterY的属性值的,设置时会提示无效
- 只有去掉控件的RenderTransformOrigin属性,才可设置RotateTransform中的CenterX和CenterY
- 当设置
<RotateTransform x:Name="rt" Angle="0" CenterX="0" CenterY="0"/>
后效果如下:
2 CenterX和CenterY
对于CenterX和CenterY的属性值的理解:
CenterX和CenterY的属性值 设置的是实际 尺寸,而非比例,注意与RenderTransformOrigin区分
3 基于RotateTransform的 加载动画
可以考虑使用一个loading的PNG图片,或者从iconfont上下载图标资源,然后使用RotateTransform实现一个简单的加载动画
该动画主要是通过动态改变RotateTransform 的Angle值来实现加载动画的旋转,然后辅以AccelerationRatio="0.55" DecelerationRatio="0.45"
属性值的设置,让加载动画显得更自然
加载动画代码如下:
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Storyboard x:Key="StartLoadingStoryboard">
<DoubleAnimation Duration="0:0:2" To="360" AccelerationRatio="0.55" DecelerationRatio="0.45" RepeatBehavior="Forever" Storyboard.TargetName="rt" Storyboard.TargetProperty="Angle"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btn" >
<BeginStoryboard Storyboard="{StaticResource StartLoadingStoryboard}"></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid Background="LightGreen">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image x:Name="img" Height="50" Source="/MvvmDemo;component/Res/Images/loading.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<RotateTransform x:Name="rt" Angle="0"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<Button x:Name="btn" Height="60" Width="160" Margin="50" Content="测试"></Button>
</StackPanel>
</Grid>
</UserControl>
四、ScaleTransform(缩放)
1 ScaleTransform介绍
ScaleTransform的作用就是让对象的大小发生变化,放大或缩小对象
当我们调整ScaleTransform的ScaleX属性和ScaleY属性的时候,控件就会放大或缩小
2 基于ScaleTransform的放大缩小,翻转和展开的动画
- 当我们同时变换ScaleTransform 的ScaleX 和ScaleY属性值的就可实现放大和缩小的变化
- 当我们将
<ScaleTransform ScaleX="1"/>
逐渐变换为<ScaleTransform ScaleX="-1"/>
的过程就是一个沿着水平X轴翻转动画 - 当我们将
<ScaleTransform ScaleX="0"/>
逐渐变换为<ScaleTransform ScaleX="1"/>
的过程就是一个逐渐展开的动画
1 放大缩小动画
以上动画主要通过动画动态同时调整ScaleTransform 的ScaleX 和ScaleY属性值,实现放大缩小的效果。
放大缩小动画代码如下(示例):
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Storyboard x:Key="BigStoryboard">
<DoubleAnimation Duration="0:0:1" To="1.5" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleX"/>
<DoubleAnimation Duration="0:0:1" To="1.5" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleY"/>
</Storyboard>
<Storyboard x:Key="SmallStoryboard">
<DoubleAnimation Duration="0:0:1" To="0.5" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleX"/>
<DoubleAnimation Duration="0:0:1" To="0.5" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleY"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btn" >
<BeginStoryboard Storyboard="{StaticResource BigStoryboard}"></BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="img" >
<BeginStoryboard Storyboard="{StaticResource SmallStoryboard}"></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid Background="LightGreen">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="mainBorder" Height="200" Width="200" Background="White" CornerRadius="15">
<Image x:Name="img" Margin="15" Source="/MvvmDemo;component/Res/Images/lg.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="st" ScaleX="1"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<Button x:Name="btn" Height="60" Width="160" Margin="50" Content="测试"></Button>
</StackPanel>
</Grid>
</UserControl>
2 翻转动画
以上动画主要通过动画动态同时调整ScaleTransform 的ScaleX 属性值,实现翻转的效果。
翻转动画代码如下(示例):
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Storyboard x:Key="XturnStoryboard">
<DoubleAnimation Duration="0:0:2" To="-1" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleX"/>
</Storyboard>
<Storyboard x:Key="XturnBackStoryboard">
<DoubleAnimation Duration="0:0:2" To="1" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleX"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btn" >
<BeginStoryboard Storyboard="{StaticResource XturnStoryboard}"></BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="img" >
<BeginStoryboard Storyboard="{StaticResource XturnBackStoryboard}"></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid Background="LightGreen">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="mainBorder" Height="200" Width="200" Background="White" CornerRadius="15">
<Image x:Name="img" Margin="15" Source="/MvvmDemo;component/Res/Images/lg.png" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="st" ScaleX="1"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<Button x:Name="btn" Height="60" Width="160" Margin="50" Content="测试"></Button>
</StackPanel>
</Grid>
</UserControl>
3 展开动画
以上动画主要通过动画动态同时调整ScaleTransform 的ScaleX 属性值,将ScaleY 由0.1动态变换到1,实现展开的效果。
翻转动画代码如下(示例):
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Storyboard x:Key="OpenStoryboard">
<DoubleAnimation Duration="0:0:2" To="1" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleY"/>
</Storyboard>
<Storyboard x:Key="CloseStoryboard">
<DoubleAnimation Duration="0:0:2" To="0.1" Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleY"/>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btn" >
<BeginStoryboard Storyboard="{StaticResource OpenStoryboard}"></BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="img" >
<BeginStoryboard Storyboard="{StaticResource CloseStoryboard}"></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid Background="LightGreen">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border x:Name="mainBorder" Height="200" Width="200" Background="White" CornerRadius="15">
<Image x:Name="img" Margin="15" Source="/MvvmDemo;component/Res/Images/lg.png" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Top">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="st" ScaleY="0.1"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<Button x:Name="btn" Height="60" Width="160" Margin="50" Content="测试"></Button>
</StackPanel>
</Grid>
</UserControl>
但是这种效果,图像都有些变形了,并不是最佳的动画效果!
4 扫描效果动画
优化动画,该动画与本章内容关联不大,作为展开动画的优化版了解一下;
以上动画主要通过OpacityMask与LinearGradientBrush(径向渐变) 的组合应用来实现。
翻转动画代码如下(示例):
<UserControl x:Class="MvvmDemo.Views.ExploreView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MvvmDemo.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Storyboard x:Key="ScanStoryboard" FillBehavior="Stop">
<DoubleAnimation Duration="0:0:2" To="1" Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset"></DoubleAnimation>
<DoubleAnimation Duration="0:0:2" To="1" Storyboard.TargetName="gs3" Storyboard.TargetProperty="Offset"></DoubleAnimation>
<ThicknessAnimation Duration="0:0:2" To="0,200,0,0" Storyboard.TargetName="scan" Storyboard.TargetProperty="Margin"></ThicknessAnimation>
</Storyboard>
</UserControl.Resources>
<UserControl.Triggers>
<EventTrigger RoutedEvent="MouseLeftButtonDown" SourceName="grid" >
<BeginStoryboard Storyboard="{StaticResource ScanStoryboard}" ></BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>
<Grid x:Name="grid" Background="White">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid Height="200" Width="200">
<Grid.Background>
<ImageBrush ImageSource="/MvvmDemo;component/Res/Images/2.png"/>
</Grid.Background>
<Rectangle x:Name="scan" Height="8" Margin="0,-4,0,0" VerticalAlignment="Top" Panel.ZIndex="2" RadiusX="20" RadiusY="20">
<Rectangle.Fill>
<RadialGradientBrush Opacity="0.8">
<GradientStop Color="#FF7BF58C" Offset="0"/>
<GradientStop Color="#FF2CF53E" Offset="0.5"/>
<GradientStop Color="#80DEF7BA" Offset="1"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle>
<Rectangle.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop x:Name="gs1" Color="#ff000000" Offset="0"/>
<GradientStop x:Name="gs2" Color="#ff000000" Offset="0"/>
<GradientStop x:Name="gs3" Color="#00000000" Offset="0"/>
</LinearGradientBrush>
</Rectangle.OpacityMask>
<Rectangle.Fill>
<ImageBrush ImageSource="/MvvmDemo;component/Res/Images/lg.png"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
</StackPanel>
</Grid>
</UserControl>
这种效果,以前做人脸识别签到的项目的时候,经常会用到;比如当前画面本身为摄像头的时候画面,当检测到人脸后,需要显示人脸签到的信息,停留片刻,再回到摄像头的界面上!
实现这种效果,关键是:OpacityMask与LinearGradientBrush(径向渐变) 运用的结合
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop x:Name="gs1" Color="#ff000000" Offset="0"/>
<GradientStop x:Name="gs2" Color="#ff000000" Offset="0"/>
<GradientStop x:Name="gs3" Color="#00000000" Offset="0"/>
</LinearGradientBrush>
想要使用LinearGradientBrush 做这种动画,必须有三个渐变点GradientStop ,
我们知道当每个渐变点的Offset值不一样,就会产生渐变,
然而,当其中两个渐变点的Offset值一样,表示这两个点重合,那么这两个重合渐变点与第三个渐变点,如果颜色不一样的话,就会从视觉上产生两个区域。再辅以渐变点颜色的设置,弄一个透明区域和一个不透明区域即可。
五、SkewTransform(倾斜)
1 SkewTransform介绍
ScaleTransform的作用就是让对象的按照设置的角度倾斜
当我们调整SkewTransform的AngleX属性和AngleY属性的时候,控件会根据设置的角度倾斜
六、MatrixTranform(矩阵变换)
1 MatrixTranform介绍
表示用于在二维空间中进行转换的 3x3 仿射转换矩阵。通过操作矩阵值,可以旋转、缩放、倾斜和移动(转换)对象。
在方法和属性中,转换矩阵通常指定为只有六个成员的向量:(M11, M12, M21, M22, OffsetX, OffsetY)
<!--方式1,指定成员名赋值-->
<Button Width="100" Height="50" Content="Button">
<Button.RenderTransform>
<MatrixTransform x:Name="myMatrixTransform">
<MatrixTransform.Matrix >
<Matrix M11="3" M12="2" M21="1" M22="2" OffsetX="10" OffsetY="100"/>
</MatrixTransform.Matrix>
</MatrixTransform>
</Button.RenderTransform>
</Button>
<!--方式2:按照指定格式给Matrix属性赋值-->
<!--语法格式:”m11, m12, m21, m22, offsetX, offsetY“ -->
<Button Width="100" Height="50" Content="Button">
<Button.RenderTransform>
<MatrixTransform x:Name="myMatrixTransform2" Matrix="3,2,1,2,10,100"/>
</Button.RenderTransform>
</Button>
- 更改Matrix的 OffsetX, OffsetY的值,如同修改TranslateTransform的X和Y
2 使用MatrixTranform 实现平移,旋转,缩放,倾斜
七、TransformGroup(变换组)
使用 TransformGroup 将两个或更多 Transform 对象合并为一个复合 Transform。
<Button Content="Button" Height="30" Width="100">
<Button.RenderTransform>
<TransformGroup>
<RotateTransform Angle="45" />
<ScaleTransform ScaleX="2" ScaleY="2"/>
<SkewTransform AngleX="10" AngleY="20"/>
<TranslateTransform X="20"/>
</TransformGroup>
</Button.RenderTransform>
</Button>
八、其他
2D 变换,即是使用 2D Transform 类旋转、缩放、移动(转换)和倾斜 FrameworkElement 对象。
下表是常见转换属性
结语
以上就是本文的内容,希望以上内容可以帮助到您,如文中有不对之处,还请批评指正。
参考文档:
变换概述
当下就是最好: 简直太棒了
xiaohe_ya: 您好 请问执行命令后没反应是怎么回事呀
yanzean: 在winform中,主线程遇到await后,还是百分百由主线程执行await后面的代码,winform和WPF都是这种特殊机制
猿享天开: 博主的文章细节很到位,兼顾实用性和可操作性,感谢博主的分享
穷苦书生_万事愁: 博主的这篇文章真的让我对C#设计模式中的适配器模式有了全新的认识,细节描写非常到位,让我感受到了博主的深厚功底。期待博主接下来能够持续分享更多这样有价值的好文,同时也希望能够得到博主的指导,共同进步。在这里非常感谢博主的分享和支持!