我是靠谱客的博主 文艺鲜花,最近开发中收集的这篇文章主要介绍WPF动画详解一、概述二、简单独立动画三、场景,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

一、概述

二、简单独立动画

2.1 简单线性动画

2.2 高级动画控制

2.3 关键帧动画

2.4 特殊的关键帧

2.5 路径动画

三、场景


一、概述

动画的本质就是在一个时间段内对象位置、角度、颜色、透明度等属性值的连续变化。这些属性种,有些是对象自身的单属性,有些是图形变形 的属性。WPF规定,可以用来制作动画的属性必须是依赖属性。

简单的动画由一个元素来完成就可以了,就像一个演员的独角戏,WPF吧简单动画称为AnimationTimeline。复杂的动画就需要UI上的多个元素协同完成,就像电影中的一段场景。复杂动画的协同包括有哪些UI元素参与动画、每个元素的动画行为是什么、动画何时开始何时结束等。WPF把一组协同的动画也称为Storyboard。

二、简单独立动画

动画就是“会动的画”,而这个会动值得就是能够让UI元素或元素变形的某个属性值产生连续变化。任何一个属性都有自己的数据类型,比如UIElement的With和Height属性为Double类型、Window的Title属性为String类型。几乎针对每个可能的数据类型,WPF的动画子系统都为其准备了相应的动画类,这些动画类均派生自AnimationTimeline。3种具体动画,即简单动画、关键帧动画、沿路径运动的动画。例如:DoubleAnimationbase,它完整地派生了3个具体动画:DoubleAnimation、DoubleAnimationUsingKeyFrames和DoubleAnimationUsingPath,分别是简单动画、关键帧动画、沿路径运动的动画。

在WPF中,Double类型的属性用的最多,只讲这个类,其他亦可触类旁通。

2.1 简单线性动画

简单线性动画指仅有变化起点、变化终点、变化幅度、变化时间4个要素构成的动画。

变化时间(Duration 属性):必须指定,动画的时长多少

变化终点(To 属性):变化终点,如果没有则采用 上一次动画的终点 或 默认值

变化幅度(By 属性):变化幅度,变化的规律,使用时不可使用变化终点

变化起点(From 属性):变化起点,如果没有指定则以目标属性的当前值为起点。

让我们分析一个简单的实例。例子的XAML代码如下:

<Grid>
        <Button Width="60" Height="60" Content="Move" Click="Button_Click_1" 
                HorizontalAlignment="Left" VerticalAlignment="Top">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="30" Y="30"/>
                </Button.RenderTransform>
        </Button>
    </Grid>
</Window>

 用户界面上只包含一个Button,这个Button的RenderTransform属性值是一个名为tt的TranslateTransform对象,改变这个对象的X和Y值就会让Button的显示位置变化。Button的Click事件处理器代码如下:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();
            //指定起点
            daX.From = 30;
            daY.From = 30;
            //指定终点
            Random r = new Random();
            daX.To = r.NextDouble() * 300;
            daY.To = r.NextDouble() * 300;
            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(300));
            daX.Duration = duration;
            daY.Duration = duration;
            //动画的主题是TranslateTransform变形,而非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);
        }

因为TranslateTransform的X、Y属性均为Double类型,所以选用DoubleAnimation来产生变化。代码中声明了daX和daY两个DoubleAnimation变量并分别创建引用实例。接下来的代码一次为它们设置了起始值、终止值、变化时间。最后调用DoubleAnimation方法,让daX作用在TranslateTransformXProperty依赖属性上、让daY作用在TranslateTransform的YProperty依赖属性上。

每次单击按钮,按钮都会从起始位置向右下长宽不超过300像素的矩形内的某点运动,完成运动的时长是300毫秒。

效果:

 如果把事件处理器的代码改变成这样:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();
            //指定幅度
            daX.By= 100D;
            daY.By = 100D;
            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(300));
            daX.Duration = duration;
            daY.Duration = duration;
            //动画的主题是TranslateTransform变形,而非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);
        }

每次单击按钮,按钮都会向窗体的右下角移动。

2.2 高级动画控制

使用From、To、By、Duration几个属性进行组合就可以制作很多不同效果的动画了,然而WPF动画系统提供的控制属性远不止这些。

属性描述     应用举例
AccelerationRatio加速速率( 0.0 - 1.0)与DecelerationRatio之和不大于1.0 模拟汽车启动
DecelerationRatio   减速速率( 0.0 - 1.0)与AccelerationRatio 之和不大于1.0 模拟汽车刹车
SpeedRatio   动画实际播放速度与正常速度的比值 快进播放、慢动作
AutoReverse           是否以相反的动画方式从终点值返回到起始值倒退播放
RepeatBehavior     动画的重复行为,取0为不播放,使用double类性值可控制循环播放次数,取Forever为永远循环循环播放
BeginTime              正式开始播放前的等待时间多个动画之前的协同
EasingFunction       缓冲式渐变乒乓球弹跳效果

在这些属性中,EasingFunction是一个扩展性非常强的属性。它取值是IEasingFunction接口类型,而IEasingFunction派生类就有十几种,每个派生类都能产生不同的结束效果。比如BounceEase可以产生乒乓球弹跳的效果。

如果把前面的例子的代码改成这样:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation daX = new DoubleAnimation();
            DoubleAnimation daY = new DoubleAnimation();
            //设置反弹
            BounceEase be = new BounceEase();
            be.Bounces = 3;//弹跳3次
            be.Bounciness = 3;//弹性程度,值越大反弹越低
            daY.EasingFunction = be;
            //指定终点
            Random r = new Random();
            daX.To = r.NextDouble() * 300;
            daY.To = r.NextDouble() * 300;
            //指定时长
            Duration duration = new Duration(TimeSpan.FromMilliseconds(2000));
            daX.Duration = duration;
            daY.Duration = duration;
            //动画的主题是TranslateTransform变形,而非Button
            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);
        }

产生乒乓球弹跳的效果。

2.3 关键帧动画

动画是UI元素属性连续改变所产生的视觉效果。属性每次细微的变化都会产生一个新的画面,每个新画面就称为一“帧”,帧的连续播放就产生动画的效果。关键帧动画允许程序员为一段动画设置几个里程碑,动画执行到里程碑所在的时间点时,被动画所控制的属性值也必须达到设定的值,这些时间线上的里程碑就是关键帧。

实例:

一个Button在单击后用900毫秒的时长从左上角移动到右下角,但移动路线不是直接移动而是走“Z”字形。

我们只需创建两个DoubleAnimationUsingKeyFrames实例,一个控制TranslateTransform的X属性,一个控制TranslateTransform的Y属性。每个DoubleAnimationUsingKeyFrames各拥有三个关键帧用于指明X或Y在三个时间点(两个拐点和终点)应该达到什么样的值。

程序的XAML代码如下:

<Grid>
        <Button Width="60" Height="60" Content="Move" Click="Button_Click" 
                HorizontalAlignment="Left" VerticalAlignment="Top">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="30" Y="30"/>
                </Button.RenderTransform>
        </Button>
    </Grid>

 Button的Click事件处理器代码如下:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames dakY = new DoubleAnimationUsingKeyFrames();
            // 设置动画总时长
            dakX.Duration = new Duration(TimeSpan.FromMilliseconds(900));
            dakY.Duration = new Duration(TimeSpan.FromMilliseconds(900));
            // 创建关键帧
            LinearDoubleKeyFrame x_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame x_kf_3 = new LinearDoubleKeyFrame();
            //设置关键帧
            x_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            x_kf_1.Value = 200;
            x_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            x_kf_2.Value = 0;
            x_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            x_kf_3.Value = 200;
            //添加关键帧
            dakX.KeyFrames.Add(x_kf_1);
            dakX.KeyFrames.Add(x_kf_2);
            dakX.KeyFrames.Add(x_kf_3);
            
            LinearDoubleKeyFrame y_kf_1 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_2 = new LinearDoubleKeyFrame();
            LinearDoubleKeyFrame y_kf_3 = new LinearDoubleKeyFrame();
            y_kf_1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300));
            y_kf_1.Value = 0;
            y_kf_2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(600));
            y_kf_2.Value = 180;
            y_kf_3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(900));
            y_kf_3.Value = 180;
            dakY.KeyFrames.Add(y_kf_1);
            dakY.KeyFrames.Add(y_kf_2);
            dakY.KeyFrames.Add(y_kf_3);

            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dakX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, dakY);
        }

2.4 特殊的关键帧

DoubleAnimationUsingKeyFrames 的KeyFrames 属性的数据类型是DoubleKeyFrameCollection,此集合类可接收的类型为 DoubleKeyFrame。DoubleKeyFrame 是一个抽象类,它的所有派生类如下:

LinearDoubleKeyFrame:线性变化关键帧,目标属性值的变化时是直线性的、均匀的,即变化速率不变。

DiscreteDoubleKeyFrame:不连续变化关键帧,目标属性值的变化是跳跃性的、跃迁的。

SplineDoubleKeyFrame:样条函数式变化关键帧,目标属性的变化速率是一条贝塞尔曲线。

EasingDoubleKeyFrame:缓冲式变化关键帧,目标属性以某种缓冲形式变化。

4个派生类中最常用的是SplineDoubleKeyFrame。可以非常方面的制作非匀速动画,因为他使用一条贝塞尔曲线来控制目标属性值的变化速率。这条用于控制变化速率的贝塞尔曲线的起点是(0,0)和(1,1),分别映射着目标属性的变化起点和变化终点,意思是目标属性值由0%变化到100%。这条曲线的有两个控制点ControlPoint1和ControlPoint2,意思是曲线从起点出发先向ControlPoint1的方向前进、再向ControlPoint2的方向前进、最后到达终点,形成一条平滑的曲线。如果设置ControlPoint1和ControlPoint2的横纵坐标值相等,这是曲线成为一条直线,SplineDoubleKeyFrame和LinearDoubleKeyFrame是等价的。

下面是SplineDoubleKeyFrame的实例

程序的XAML代码如下:

<Grid>
        <Button Width="60" Height="60" Content="Move" Click="Button_Click" 
                HorizontalAlignment="Left" VerticalAlignment="Top">
            <Button.RenderTransform>
                <TranslateTransform x:Name="tt" X="30" Y="30"/>
                </Button.RenderTransform>
        </Button>
</Grid>

 Button的Click事件处理器代码如下:

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 创建动画
            DoubleAnimationUsingKeyFrames dakX = new DoubleAnimationUsingKeyFrames();
            dakX.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
            //创建、添加关键帧
            SplineDoubleKeyFrame kf = new SplineDoubleKeyFrame();
            kf.KeyTime = KeyTime.FromPercent(1);
            kf.Value = 400;
            //设置速率
            KeySpline ks = new KeySpline();
            ks.ControlPoint1 = new Point(0, 1);
            ks.ControlPoint2 = new Point(1, 0);
            kf.KeySpline = ks;
            dakX.KeyFrames.Add(kf);
            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dakX);
        }

 关键帧动画会控制Button的位置变形、让Button横向移动。整个动画只有一个关键帧,这个关键帧使用的是SplineDoubleKeyFrame变化速率控制曲线的两个控制点分别是(0,1)(1,0),目标属性会以“快-慢-快”的形式变化。

2.5 路径动画

如何让目标对象沿着一条给定的路径移动呢?答案是使用DoubleAnimationUsingPath类。DoubleAnimationUsingPath需要一个PathGeometry来指明移动路径,PathGeometry的数据信息可以用XAML的Path语法书写。PathGeometry的另一个重要属性是Source,Source属性的数据类型是PathAnimationSource枚举,枚举值可取X(关注曲线上每一点横坐标的变化)、Y(关注曲线上每一点纵坐标的变化)或Angle关注曲线上每一点处切线方向的变化。

实例:

让Button沿着一条贝塞尔曲线做波浪形运动。程序XAML代码如下:

<Grid>
        <Grid x:Name="LayoutRoot">
            <!--移动路径-->
            <Grid.Resources>
                <PathGeometry x:Key="movingPath" 
            	Figures="M 0,150 C 300,-100 300,400 600,120"/>
            </Grid.Resources>
            <Button Content="Move" HorizontalAlignment="Left" VerticalAlignment="Top"
                Width="80" Height="80" Click="Button_Click">
                <Button.RenderTransform>
                    <TranslateTransform x:Name="tt" X="0" Y="0"/>
                </Button.RenderTransform>
            </Button>
        </Grid>
</Grid>

Button的Click事件处理器代码如下:

private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 查找资源
            PathGeometry pg = this.LayoutRoot.FindResource("movingPath") as PathGeometry;
            Duration duration = new Duration(TimeSpan.FromMilliseconds(600));// 设置动画时间
            // 创建动画
            DoubleAnimationUsingPath dapX = new DoubleAnimationUsingPath();
            dapX.PathGeometry = pg;
            dapX.Source = PathAnimationSource.X;
            dapX.Duration = duration;

            DoubleAnimationUsingPath dapY = new DoubleAnimationUsingPath();
            dapY.PathGeometry = pg;
            dapY.Source = PathAnimationSource.Y;
            dapY.Duration = duration;

            //设置来回循环效果
            dapX.AutoReverse = true;
            dapX.RepeatBehavior = RepeatBehavior.Forever;
            dapY.AutoReverse = true;
            dapY.RepeatBehavior = RepeatBehavior.Forever;
            //执行动画
            this.tt.BeginAnimation(TranslateTransform.XProperty, dapX);
            this.tt.BeginAnimation(TranslateTransform.YProperty, dapY);
        }

三、场景

场景就是并行执行的一组动画。

先是把一组独立的动画组织在一个Storyboard元素中、安排好他们的协作关系,然后制定哪个动画由哪个UI元素、哪个属性负责完成。Storyboard设计好后,你可以为他选择一个恰当的触发时机,比如按钮按下或下载开始时。一旦触发条件被满足,动画产经就会开始执行。

实例:

程序XAML代码如下:

<Grid Margin="6">
        <!--布局控制-->
        <Grid.RowDefinitions>
            <RowDefinition Height="38"/>
            <RowDefinition Height="38"/>
            <RowDefinition Height="38"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="60"/>
        </Grid.ColumnDefinitions>
        <!--跑道红-->
        <Border BorderBrush="Gray" BorderThickness="1" Grid.Row="0">
            <Ellipse x:Name="ballR" Height="36" Width="36" Fill="Red"
                     HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttR"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--跑道绿-->
        <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="1">
            <Ellipse x:Name="ballG" Height="36" Width="36" Fill="LawnGreen"
                     HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttG"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--跑道蓝-->
        <Border BorderBrush="Gray" BorderThickness="1,0,1,1" Grid.Row="2">
            <Ellipse x:Name="ballB" Height="36" Width="36" Fill="Blue"
                     HorizontalAlignment="Left">
                <Ellipse.RenderTransform>
                    <TranslateTransform x:Name="ttB"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </Border>
        <!--按钮-->
        <Button Content="Go!" Grid.Column="1" Grid.RowSpan="3">
            <!--按钮触发-->
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard Duration="0:0:0.6">
                           <!--红色小球动画-->
                            <DoubleAnimation Duration="0:0:0.6" To="400"
                                 Storyboard.TargetName="ttR"
                                 Storyboard.TargetProperty="X"/>
                            <!--绿色小球动画-->
                            <DoubleAnimationUsingKeyFrames Duration="0:0:0.6"
                        Storyboard.TargetName="ttG" Storyboard.TargetProperty="X">
                                <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400"
                                          KeySpline="0,1,1,0"/>
                            </DoubleAnimationUsingKeyFrames>
                            <!--蓝色小球动画-->
                            <DoubleAnimationUsingKeyFrames Duration="0:0:0.6"
                        Storyboard.TargetName="ttB" Storyboard.TargetProperty="X">
                                <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="400"
                                          KeySpline="1,0,0,1"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Grid>

 效果:

最后

以上就是文艺鲜花为你收集整理的WPF动画详解一、概述二、简单独立动画三、场景的全部内容,希望文章能够帮你解决WPF动画详解一、概述二、简单独立动画三、场景所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(36)

评论列表共有 0 条评论

立即
投稿
返回
顶部