WPF 动画:同为控件不同命

作者 : 开心源码 本文共5607个字,预计阅读时间需要15分钟 发布时间: 2022-05-12 共267人阅读

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 效果

image

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 效果

image

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 效果

image

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 效果

image

这看起来还挺正常。但假如你想要宽高同时放大呢?

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 效果

image

这种并不是我们想要的结果。

把两个动画的开始时间错开,也不是客户想要的。

所以,我们更喜欢将动画分发给 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 效果

image

5.总结

  1. 对于 Button,你可以通过 Width|Height、RenderTransform、父元素 ViewBox 的方式进行:宽、高、宽高同时,这 3 种的动画缩放。
  2. 对于 Window,你可以通过 Width|Height、RenderTransform 进行宽或者高的缩放,但假如要同时缩放宽高,我们用 RenderTransform.
  3. 内容将同步到微信公众号:广州 WPF 开发

    广州 WPF 开发.jpg

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » WPF 动画:同为控件不同命

发表回复