WPF 动画:同为控件不同命 - 简书
1. 及格与优秀
读大学的时候,有一门课的作业是用 PPT 展示。
但是我们很多同学都把 PPT 当做 Word 来用,就单纯地往里面堆文字。
大家都单纯地从一页堆积的文字翻到另一页堆积的文字,以致于台下的同学都听不下去,包括那些以同样的方式汇报的同学。
本来以为会在枯燥中期待下课的到来,直到有个叫幽灵东的同学汇报,他惊艳到了我们。
相比别人单纯地堆积文字,他更多的采用图片+较少的文字的方式。
同时,那些图片和文字的出现、出现顺序、消失,都采用了动画。这些经过设计的动画,串联起来之后,竟让我们观众像是在看一部小动漫。
我们不禁都盯着屏幕,赞叹着正在呈现的动画,同时又期待着下一个动画。
2. 动起来的软件
而对于我们的 Windows 软件或 网站,在实现基础的业务功能后,做一些"增值"的动画效果,会让我们的系统看起来,更有趣。
所以,有时候,我们会在鼠标移入按钮时,让按钮缓慢变大;
又或者打开一个子窗口的时候,让这个子窗口以动画的方式出现在我们面前,例如:像一幅画一样,从左到右展开的方式。
这两种动画都是在控件的尺寸上做手脚。
然而,今天我们要讲的重点是:
虽然按钮(System.Windows.Controls.Button 类)和窗口(System.Windows.Window 类) 都继承自 System.Window.Controls.ContentControl。
它们实现缩放动画的方式,却有些出入。
3. Button 的缩放实现
当你想对 Button 进行缩放时,你可以通过对不同的属性分发动画,来实现该效果。
3.1 基于 Width 和 Height 的动画
即:将动画分发给 Button 的 Width 和 Height 属性,从而实现 Button 的缩放。
3.1.1 代码
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" To="180" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="180" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
3.1.2 效果
3.2 基于 RenderTransform 的动画
跟 Width 一样,RenderTransform 也是 Button 的依赖项属性。
它的值类型为 System.Windows.Media.Transform,这个类是定义在二维平面上启用变换的功能,包括旋转、缩放、扭曲、平移。
System.Windows.Media.Transform 的子类 System.Windows.Media.ScaleTransform ,就是实现在二维 x-y 坐标系内缩放对象。
所以下面我们会用到它。
3.2.1 代码
<Style TargetType="{x:Type Button}" x:Key="zoomByScale">
<!--设置元素的重点为转换的中心点-->
<Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
<!--设置转换信息为(或往转换信息里添加)缩放-->
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform></ScaleTransform>
</Setter.Value>
</Setter>
<!--鼠标移入时,将动画分发给 ScaleTransform 的 ScaleX、ScaleY 属性-->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="1" To="1.2" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="0:0:6"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="1" To="1.2" Duration="0:0:0.5" AutoReverse="True" RepeatBehavior="0:0:6"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
3.2.2 效果
3.2.3 附件
| 属性 | 摘要 | 备注 |
|---|---|---|
| RenderTransform | 获取或设置影响此元素的呈现位置的转换信息 | 依赖项属性,值为 System.Windows.Media.Transform 类的对象 |
| ScaleTransform | 在二维 x-y 坐标系内缩放对象 | 继承自 Transform 类 |
| ScaleX | 获取或设置 x 轴的缩放比例 | ScaleTransform 的成员。默认值为 1 |
| RotateTransform | 在 二维 x-y 坐标系内围绕指定点按照顺时针方向旋转对象。 | 继承自 Transform 类 |
| Angle | 获取或设置顺时针旋转角度(以度为单位) | RotateTransform 的成员。默认值为 0 |
3.3 Viewbox 的一次性缩放
3.3.1 代码
<Grid Width="300" Height="300">
<Viewbox Width="150" Height="150" x:Name="vb_ChangeSizeButton">
<Button Width="150" Height="150" Content="Viewbox 带我飞"/>
</Viewbox>
<StackPanel Margin="15" HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal">
<Button Margin="10" Click="Zoom_Big" Cursor="Hand" Content="+"/>
<Button Margin="10" Click="Zoom_Small" Cursor="Hand" Content="——" />
</StackPanel>
</Grid>
// 将 viewBox 的尺寸放大到 1.2 倍
private void Zoom_Big(object sender, RoutedEventArgs e)
{
vb_ChangeSizeButton.Width = vb_ChangeSizeButton.Width * 1.2;
vb_ChangeSizeButton.Height = vb_ChangeSizeButton.Height * 1.2;
}
// 将 viewBox 的尺寸除以 1.2
private void Zoom_Small(object sender, RoutedEventArgs e)
{
vb_ChangeSizeButton.Width = vb_ChangeSizeButton.Width / 1.2;
vb_ChangeSizeButton.Height = vb_ChangeSizeButton.Height / 1.2;
}
3.3.2 解释
当 viewbox 的尺寸改变时,子元素大小缩放的倍数等同于 viewbox 的缩放倍数。
3.3.3 效果
4. Window 的缩放
对于 Window 的动画,我们一般是分发给它的 RenderTransform 属性。
Width 或 Height 虽然也可以,但是无法实现同时缩放宽高。
既然提到了,我们就先来看看。
4.1 Window 基于 Width 和 Height 的动画
4.1.1 动画只分发给 Width 属性
4.1.1.1 代码
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource {x:Type Window}}">
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="ResizeMode" Value="CanResizeWithGrip" />
<Style.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" From="0" To="300" Duration="0:0:0.6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Style>
4.1.1.2 效果
这看起来还挺正常。但如果你想要宽高同时放大呢?
4.1.2 Window 基于 Width 和 Height 的蹩脚动画
4.1.2.1 代码
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource {x:Type Window}}">
...
<Style.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" From="0" To="300" Duration="0:0:0.6"/>
<DoubleAnimation Storyboard.TargetProperty="Height" From="0" To="300" Duration="0:0:0.6"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Style>
4.1.2.2 效果
这种并不是我们想要的结果。
把两个动画的开始时间错开,也不是用户想要的。
所以,我们更喜欢将动画分发给 RenderTransform 属性。
4.2 window 基于 RenderTransform 的动画
这里将仅对 ScaleX 放大的情况一笔带过了..
image
4.2.1 将动画分发给 ScaleX 和 ScaleY,实现宽高同时放大的代码
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource {x:Type Window}}">
...
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform></ScaleTransform>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleX" From="0" To="1" Duration="0:0:0.6" AccelerationRatio="0.7"/>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.ScaleY" From="0" To="1" Duration="0:0:0.6" AccelerationRatio="0.7"/>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Style>
4.2.2 效果
5.总结
- 对于 Button,你可以通过 Width|Height、RenderTransform、父元素 ViewBox 的方式进行:宽、高、宽高同时,这 3 种的动画缩放。
- 对于 Window,你可以通过 Width|Height、RenderTransform 进行宽或高的缩放,但如果要同时缩放宽高,我们用 RenderTransform.
内容将同步到微信公众号:广州 WPF 开发
广州 WPF 开发.jpg
WPF 动画:同为控件不同命 - 简书的更多相关文章
- c#字符串加载wpf控件模板代码 - 简书
原文:c#字符串加载wpf控件模板代码 - 简书 ResourceManager resManagerA = new ResourceManager("cn.qssq666.Properti ...
- WPF Step By Step 控件介绍
WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...
- WPF中的ControlTemplate(控件模板)(转)
原文地址 http://www.cnblogs.com/zhouyinhui/archive/2007/03/28/690993.html WPF中的ControlTemplate(控件模板) ...
- WPF中的ControlTemplate(控件模板)
原文:WPF中的ControlTemplate(控件模板) WPF中的ControlTemplate(控件模板) ...
- wpf XMAL中隐藏控件
原文:wpf XMAL中隐藏控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a771948524/article/details/9264569 ...
- [转]WPF中的ControlTemplate(控件模板)
WPF中的ControlTemplate(控件模板) ...
- 在WPF中使用WinForm控件方法
1. 首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2. 在要使用WinForm控 ...
- CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09)
事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便支持wpf的开发,同时,框架仍保留最低.net framework2.0 ...
- WPF中的image控件的Source赋值
WPF中的Image控件Source的设置 1.XAML中 简单的方式(Source="haha.png"); image控件的Source设置为相对路径后(Source=&quo ...
随机推荐
- java 包(package)
package packageDemo2_5; public class packageDemo1 { String name;//同一个包里的类可以直接访问 //不同包里的类是不可以使用默认修饰符的 ...
- 【[JXOI2017]加法】
江西竟然还有省选,而且还是可怜题,实在是有点可怕 这道题还是比较清真的,大概是最简单的可怜题? 首先看到最大值最小,就很容易想到了二分答案 对于一个二分出来的答案\(mid\),去把原数列扫一遍就可以 ...
- P2149 [SDOI2009]Elaxia的路线
题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在 ...
- 2019.3.25 IDEA控制台乱码解决 &&idea关闭代码自动提示
设置Tomcat里面的conf文件夹下的properties结尾的文件
- Golang 单元测试和性能测试
开发程序其中很重要的一点是测试,我们如何保证代码的质量,如何保证每个函数是可运行,运行结果是正确的,又如何保证写出来的代码性能是好的,我们知道单元测试的重点在于发现程序设计或实现的逻辑错误,使问题及早 ...
- CUDA 纹理的使用
纹理绑定有两种,一个是绑定到线性内存就是用cudaMalloc();cudaMemcpy();开辟的内存空间,另一种是绑定到cudaMallocArray, cudaMemcpyToArray开辟到的 ...
- linux日志log查询常用命令
一般的log文件都是需要过滤 1.grep 过滤查找 查询ip 221.2.100.138的log grep '221.2.100.138' web.access.log grep 221.2.10 ...
- 使用Apache HttpClient 4.x进行异常重试
在进行http请求时,难免会遇到请求失败的情况,失败后需要重新请求,尝试再次获取数据. Apache的HttpClient提供了异常重试机制,在该机制中,我们可以很灵活的定义在哪些异常情况下进行重试. ...
- HDU 3635 Dragon Balls(超级经典的带权并查集!!!新手入门)
Dragon Balls Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- f-stack中nginx配置后make出现error: ignoring return value of ‘ftruncate’
问题 Nginx 配置后 make 出现error: src/os/unix/ngx_process_cycle.c: In function 'ngx_start_worker_processes' ...