博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF绘图与动画(四)
阅读量:5910 次
发布时间:2019-06-19

本文共 9245 字,大约阅读时间需要 30 分钟。

 

  WPF规定,可以用来制作动画的属性必须是依赖属性。

  Timeline、AnimationTimeline和Storyboard

  

  ⒈简单线性动画

    所谓“简单线性动画”就是指仅由变化起点、变化终点、变化幅度、变化时间4个要素构成的动画。

      变化时间(Duration属性):必须指定,数据类型为Duration。

      变化终点(To属性):如果没有指定变化终点,程序将采用上一次动画的终点或默认值。

      变化幅度(By属性):如果同时指定了变化终点,变化幅度将被忽略。

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

  

  

private void Button_OnClick(object sender, RoutedEventArgs e)        {            DoubleAnimation daX=new DoubleAnimation();            DoubleAnimation daY=new DoubleAnimation();            //指定起点            daX.From = 0D;            daY.From = 0D;                        //指定终点            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);        }

    这段代码有以下几处值得注意的地方:

      ⒈因为指定了daX和daY的起始值为0,所以每次按钮都会“跳”回窗体的左上角开始动画。如果想让按钮从当前位置开始下一次动画,只需要把“daX.From=0D;”和“daY.From=0D;”两句代码移除即可。

      ⒉尽管表现出来的是Button在移动,但DoubleAnimation的作用目标并不是Button而是TranslateTransform实例,因为TranslateTransform实例是Button的RenderTransform属性值,所以Button“看上去”是移动。

      ⒊能用来制作动画的属性必须是依赖属性,TranslateTransform的XProperty和YProperty就是两个依赖属性。

      ⒋UIElement和Animatable两个类都定义有BeginAnimation这个方法,TranslateTransform派生自Animatable类,所以具有这个方法,这个方法的调用者就是动画要作用的目标对象,两个参数分别指明被用作依赖属性(TranslateTransform.XProperty和TranslateTransform.XProperty)和设计好的动画(daX和daY),可以猜想,如果需要动画改编Button的宽度或高度(这两个属性也是Double类型),也应该先创建DoubleAnimation实例,然后设置起始值和动画时间,最后用Button的BeginAnimation方法、使用动画对象影响Buttion.WidthProperty和Button.HeightProperty。

 

    ⒉高级动画控制

      使用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类型值可控制循环次数,取RepeatBehavior.Forever为永远循环 循环播放
BeginTime 正式开始播放前的等待时间 多个动画之前的协同
EasingFunction 缓冲式渐变 乒乓球弹跳效果

      对于这些属性,大家可以自己动手尝试----对它们进行组合往往可以产生很多意想不到的效果。

      在这些属性中,EasingFunction是一个扩展性非常强的属性。它的取值是IEasingFunction接口类型,为WPF自带的IEasingFunction派生类就有十多种,每个派生类都能产生不停的结束效果。比如BounceEase可以产生乒乓球弹跳式的效果,我们可以直接拿来使用而不必花精力去亲自创作。

private void Button_OnClick(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;                        //指定起点            daX.From = 0D;            daY.From = 0D;            //指定终点            daX.To = 300;            daY.To = 300;            //指定时长            Duration duration = new Duration(TimeSpan.FromMilliseconds(3000));            daX.Duration = duration;            daY.Duration = duration;            //动画的主体是TranslateTransform变形,而非Button            this.tt.BeginAnimation(TranslateTransform.XProperty, daX);            this.tt.BeginAnimation(TranslateTransform.YProperty, daY);        }

    ⒊关键帧动画

      动画是UI元素属性连续改变所产生的视觉效果。属性每次细微的变化都会产生一个新的画面,每个新画面就称为一“帧”,帧的连续播放就产生动画效果。如同电影一样,单位时间内播放的帧数越多,动画的效果就越细致。前面讲到的简单动画只设置了一个起点和终点,之间的动画帧都是由程序计算出来并绘制的,程序员无法进行控制。关键帧动画则允许程序员为一段动画设置几个“里程碑”,动画执行到里程碑所在的时间点时,被动画所控制的属性值也必须达到设定的值,这些时间线上的“里程碑”就是关键帧。

  

private void Button_OnClick(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);        }

  使用 KeyTime.FromPercent静态方法则可以获得以百分比计算单的相对时间点,程序将整个关键帧动画的时长(Duration)视为100%。

x_kf_1.KeyTime = KeyTime.FromPercent(0.33);            x_kf_1.Value = 200;            x_kf_2.KeyTime = KeyTime.FromPercent(0.66);            x_kf_2.Value = 0;            x_kf_3.KeyTime = KeyTime.FromPercent(1.0);            x_kf_3.Value = 200;

  之后无论你把dakX的Duration改为多少,三个关键帧都会将整个动画分割为均等的三段。

    ⒋特殊的关键帧

      DoubleAnimationUsingKeyFrames的KeyFrames属性的数据类型是DoubleKeyFrameCollection,此集合类可接收的元素类型为DoubleKeyFrame。DoubleKeyFrame是一个抽象类,前面使用的LinearDoubleKeyFrame就是它的派生类之一。DoubleKeyFrame的所有派生类如下:

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

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

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

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

    4个派生类中最常用的是SplineDoubleKeyFrame(SplineDoubleKeyFrame可以替代LinearDoubleKeyFrame)。

 

  

private void Button_OnClick(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);        }

      ⒌路径动画

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

        

private void Button_OnClick(object sender, RoutedEventArgs e)        {            // 从XAML代码中获取移动路径数据            System.Windows.Media.PathGeometry pg=this.LayoutRoot.FindResource("movingPath") as System.Windows.Media.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);        }

  

  

转载于:https://www.cnblogs.com/bjxingch/articles/7862695.html

你可能感兴趣的文章
MarkdownPad2.5 注册码
查看>>
mybatis指定jdbctype
查看>>
pat解题报告【1082】
查看>>
Java IO详解(七)------随机访问文件流
查看>>
Ubuntu下errno值
查看>>
HDU 4786 Fibonacci Tree 最小生成树
查看>>
docker实践4
查看>>
selenium测试(Java)--多表单切换(十二)
查看>>
广义线性模型 - Andrew Ng机器学习公开课笔记1.6
查看>>
PHP自学,第一阶段,基础学习
查看>>
curl命令使用
查看>>
Ubuntu 12.04将默认集成Landscape管理套件【转】
查看>>
Windows 7安装超级终端连接COM口设备
查看>>
迭代器模式
查看>>
oracle获取过去两年的今天时间
查看>>
微信小程序登录JAVA后台
查看>>
如何恢复回收站删除的文件
查看>>
Android 模拟器下载、编译及调试
查看>>
findbugs静态代码分析工具使用教程
查看>>
TERMIOS详解【转】
查看>>