博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF:Animation动画--CustomAnimation自定义动画(1)
阅读量:6759 次
发布时间:2019-06-26

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

CustomAnimation自定义动画

clipboard.png

实现效果:

1、X轴上各种缓动动画效果
2、自定义动画代码实现
文件组织:

clipboard.png

一、界面代码

  1. 界面容器为Grid方格下使用Canvas,Canvas承载TextBlock和Button
  2. 动画开始的操作有两种方式,一种为点击Go按钮执行所有动画,一种为单独单击按钮会执行相应按钮动画+第一个Linear按钮动画。
  3. 演示板作为静态资源共享,统一在页面加载触发器,触发条件为上面的2种操作方式。

主要BounceEase、ElasticEase、circle按钮布置代码:

Bounce!

主要演示板资源代码:

弹跳BounceDoubleAnimation注册属性有:EdgeBehavior

弹簧动画:ElasticDoubleAnimation

圆圈BounceEase动画:

ps:其中注释部分是可以省掉而不影响实现效果。

  1. Circle1动画为沿X轴绕圈运动
  2. Circle2d动画为在X轴上一点原地绕圈运动,然后平移到终点,注意动画X值点与时间线配合。

统一触发代码:

后台代码:

本实例自定义实现缓动函数EasingFunctionBase的一部分具体子效果,在xaml示例中还可以设置各项缓动效果的属性参数,详细见第2章。
BounceAnimation弹球动画自定义:

  1. Bounce自定义弹球算法:此处不详述,只知道有个大概方法,获取特定公式函数值,然后根据EaseMode来增减量返回
  2. .Net中BounceEase与此原理相识,都可以设置Bounces、Bounciness参数
protected override double GetCurrentValueCore(    double defaultOriginValue,    double defaultDestinationValue,    AnimationClock clock){    double returnValue;    var start = From ?? defaultOriginValue;    var delta = To - start ?? defaultOriginValue - start;    switch (EdgeBehavior)    {        case EdgeBehaviorEnum.EaseIn:            returnValue = EaseIn(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);            break;        case EdgeBehaviorEnum.EaseOut:            returnValue = EaseOut(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);            break;        default:            returnValue = EaseInOut(clock.CurrentProgress.Value, start, delta, Bounciness, Bounces);            break;    }    return returnValue;}protected override Freezable CreateInstanceCore() => new BounceDoubleAnimation();private static double EaseOut(double timeFraction, double start, double delta, double bounciness, int bounces){    // math magic: The cosine gives us the right wave, the timeFraction is the frequency of the wave,     // the absolute value keeps every value positive (so it "bounces" off the midpoint of the cosine     // wave, and the amplitude (the exponent) makes the sine wave get smaller and smaller at the end.    var returnValue = Math.Abs(Math.Pow((1 - timeFraction), bounciness)                               *Math.Cos(2*Math.PI*timeFraction*bounces));    returnValue = delta - (returnValue*delta);    returnValue += start;    return returnValue;}private static double EaseIn(double timeFraction, double start, double delta, double bounciness, int bounces){    // math magic: The cosine gives us the right wave, the timeFraction is the amplitude of the wave,     // the absolute value keeps every value positive (so it "bounces" off the midpoint of the cosine     // wave, and the amplitude (the exponent) makes the sine wave get bigger and bigger towards the end.    var returnValue = Math.Abs(Math.Pow((timeFraction), bounciness)                               *Math.Cos(2*Math.PI*timeFraction*bounces));    returnValue = returnValue*delta;    returnValue += start;    return returnValue;}private static double EaseInOut(double timeFraction, double start, double delta, double bounciness, int bounces){    double returnValue;    // we cut each effect in half by multiplying the time fraction by two and halving the distance.    if (timeFraction <= 0.5)    {        returnValue = EaseIn(timeFraction*2, start, delta/2, bounciness, bounces);    }    else    {        returnValue = EaseOut((timeFraction - 0.5)*2, start, delta/2, bounciness, bounces);        returnValue += delta/2;    }    return returnValue;}

ElasticDoubleAnimation弹簧动画自定义

  1. 弹簧动画,结构方式与上面类似,其属性参与类似ElasticEaseh缓动函数
  2. 算法如下:
protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue,    AnimationClock clock){    double returnValue;    var start = From ?? defaultOriginValue;    var delta = To - start ?? defaultOriginValue - start;    switch (EdgeBehavior)    {        case EdgeBehaviorEnum.EaseIn:            returnValue = EaseIn(clock.CurrentProgress.Value, start, delta, Springiness, Oscillations);            break;        case EdgeBehaviorEnum.EaseOut:            returnValue = EaseOut(clock.CurrentProgress.Value, start, delta, Springiness, Oscillations);            break;        default:            returnValue = EaseInOut(clock.CurrentProgress.Value, start, delta, Springiness, Oscillations);            break;    }    return returnValue;}protected override Freezable CreateInstanceCore() => new ElasticDoubleAnimation();private static double EaseOut(double timeFraction, double start, double delta, double springiness,    double oscillations){    // math magic: The cosine gives us the right wave, the timeFraction * the # of oscillations is the     // frequency of the wave, and the amplitude (the exponent) makes the wave get smaller at the end    // by the "springiness" factor. This is extremely similar to the bounce equation.    var returnValue = Math.Pow((1 - timeFraction), springiness)                      *Math.Cos(2*Math.PI*timeFraction*oscillations);    returnValue = delta - (returnValue*delta);    returnValue += start;    return returnValue;}private static double EaseIn(double timeFraction, double start, double delta, double springiness,    double oscillations){    // math magic: The cosine gives us the right wave, the timeFraction * the # of oscillations is the     // frequency of the wave, and the amplitude (the exponent) makes the wave get smaller at the beginning    // by the "springiness" factor. This is extremely similar to the bounce equation.     var returnValue = Math.Pow((timeFraction), springiness)                      *Math.Cos(2*Math.PI*timeFraction*oscillations);    returnValue = returnValue*delta;    returnValue += start;    return returnValue;}private static double EaseInOut(double timeFraction, double start, double delta, double springiness,    double oscillations){    double returnValue;    // we cut each effect in half by multiplying the time fraction by two and halving the distance.    if (timeFraction <= 0.5)    {        return EaseIn(timeFraction*2, start, delta/2, springiness, oscillations);    }    returnValue = EaseOut((timeFraction - 0.5)*2, start, delta/2, springiness, oscillations);    returnValue += (delta/2);    return returnValue;}}

CircleAnimation圆圈动画自定义:

  1. 与.NET的CircleEase完全不同,后者无设置参数,而前者有X、Y方向、半径大小属性参数。
  2. 另外是原地圆圈运动,所有不像上述自定义属性From/To等
  3. 同时确定X、Y轴方向动画形成了原地圆圈动画,且看其简约的代码:
/// ///     CircleAnimation: calculates polar coordinates as a function of time.///     Use two of these (XDirection and YDirection) to move an element in an elliptical manner/// public class CircleAnimation : DoubleAnimationBase{    public enum DirectionEnum    {        XDirection,        YDirection    }    public static readonly DependencyProperty DirectionProperty =        DependencyProperty.Register("Direction", typeof (DirectionEnum), typeof (CircleAnimation),            new PropertyMetadata(DirectionEnum.XDirection));    public static readonly DependencyProperty RadiusProperty =        DependencyProperty.Register("Radius", typeof (double), typeof (CircleAnimation),            new PropertyMetadata((double) 10));    ///     ///     distance from origin to polar coordinate    ///     public double Radius    {        get { return (double) GetValue(RadiusProperty); }        set        {            if (value > 0.0)            {                SetValue(RadiusProperty, value);            }            else            {                throw new ArgumentException("a radius of " + value + " is not allowed!");            }        }    }    ///     ///     are we measuring in the X or Y direction?    ///     public DirectionEnum Direction    {        get { return (DirectionEnum) GetValue(DirectionProperty); }        set { SetValue(DirectionProperty, value); }    }    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue,        AnimationClock clock)    {        var time = clock.CurrentProgress.Value;        // math magic: calculate new coordinates using polar coordinate equations. This requires two         // animations to be wired up in order to move in a circle, since we don't make any assumptions        // about what we're animating (e.g. a TranslateTransform).         var returnValue = Direction == DirectionEnum.XDirection            ? Math.Cos(2*Math.PI*time)            : Math.Sin(2*Math.PI*time);        // Need to add the defaultOriginValue so that composition works.        return returnValue*Radius + defaultOriginValue;    }    protected override Freezable CreateInstanceCore() => new CircleAnimation();}

BackDoubleAnimation后退下动画效果

  1. 同理BackDoubleAnimation自定义动画与BackEase参数不一样,前者只有Amplitude/Suppression,h后者只有Amplitudesh属性。
  2. 完整代码如下:
/// ///     BackDoubleAnimation: goes in the opposite direction first/// public class BackDoubleAnimation : DoubleAnimationBase{    public enum EdgeBehaviorEnum    {        EaseIn,        EaseOut,        EaseInOut    }    public static readonly DependencyProperty EdgeBehaviorProperty =        DependencyProperty.Register("EdgeBehavior", typeof (EdgeBehaviorEnum), typeof (BackDoubleAnimation),            new PropertyMetadata(EdgeBehaviorEnum.EaseIn));    public static readonly DependencyProperty AmplitudeProperty =        DependencyProperty.Register("Amplitude", typeof (double), typeof (BackDoubleAnimation),            new PropertyMetadata(4.0));    public static readonly DependencyProperty SuppressionProperty =        DependencyProperty.Register("Suppression", typeof (double), typeof (BackDoubleAnimation),            new PropertyMetadata(2.0));    public static readonly DependencyProperty FromProperty =        DependencyProperty.Register("From",            typeof (double?),            typeof (BackDoubleAnimation),            new PropertyMetadata(null));    public static readonly DependencyProperty ToProperty =        DependencyProperty.Register("To",            typeof (double?),            typeof (BackDoubleAnimation),            new PropertyMetadata(null));    ///     ///     which side gets the effect    ///     public EdgeBehaviorEnum EdgeBehavior    {        get { return (EdgeBehaviorEnum) GetValue(EdgeBehaviorProperty); }        set { SetValue(EdgeBehaviorProperty, value); }    }    ///     ///     how much backwards motion is there in the effect    ///     public double Amplitude    {        get { return (double) GetValue(AmplitudeProperty); }        set { SetValue(AmplitudeProperty, value); }    }    ///     ///     how quickly the effect drops off vs. the entire timeline    ///     public double Suppression    {        get { return (double) GetValue(SuppressionProperty); }        set { SetValue(SuppressionProperty, value); }    }    ///     ///     Specifies the starting value of the animation.    ///     public double? From    {        get { return (double?) GetValue(FromProperty); }        set { SetValue(FromProperty, value); }    }    ///     ///     Specifies the ending value of the animation.    ///     public double? To    {        get { return (double?) GetValue(ToProperty); }        set { SetValue(ToProperty, value); }    }    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue,        AnimationClock clock)    {        double returnValue;        var start = From ?? defaultOriginValue;        var delta = To - start ?? defaultOriginValue - start;        switch (EdgeBehavior)        {            case EdgeBehaviorEnum.EaseIn:                returnValue = EaseIn(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);                break;            case EdgeBehaviorEnum.EaseOut:                returnValue = EaseOut(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);                break;            default:                returnValue = EaseInOut(clock.CurrentProgress.Value, start, delta, Amplitude, Suppression);                break;        }        return returnValue;    }    protected override Freezable CreateInstanceCore() => new BackDoubleAnimation();    private static double EaseOut(double timeFraction, double start, double delta, double amplitude,        double suppression)    {        var frequency = 0.5;        // math magic: The sine gives us the right wave, the timeFraction * 0.5 (frequency) gives us only half         // of the full wave, the amplitude gives us the relative height of the peak, and the exponent makes the         // effect drop off more quickly by the "suppression" factor.         var returnValue = Math.Pow((timeFraction), suppression)                          *amplitude*Math.Sin(2*Math.PI*timeFraction*frequency) + timeFraction;        returnValue = (returnValue*delta);        returnValue += start;        return returnValue;    }    private static double EaseIn(double timeFraction, double start, double delta, double amplitude,        double suppression)    {        var frequency = 0.5;        // math magic: The sine gives us the right wave, the timeFraction * 0.5 (frequency) gives us only half         // of the full wave (flipped by multiplying by -1 so that we go "backwards" first), the amplitude gives         // us the relative height of the peak, and the exponent makes the effect start later by the "suppression"         // factor.         var returnValue = Math.Pow((1 - timeFraction), suppression)                          *amplitude*Math.Sin(2*Math.PI*timeFraction*frequency)*-1 + timeFraction;        returnValue = (returnValue*delta);        returnValue += start;        return returnValue;    }    private static double EaseInOut(double timeFraction, double start, double delta, double amplitude,        double suppression)    {        double returnValue;        // we cut each effect in half by multiplying the time fraction by two and halving the distance.        if (timeFraction <= 0.5)        {            return EaseIn(timeFraction*2, start, delta/2, amplitude, suppression);        }        returnValue = EaseOut((timeFraction - 0.5)*2, start, delta/2, amplitude, suppression);        returnValue += (delta/2);        return returnValue;    }}

转载地址:http://vwzeo.baihongyu.com/

你可能感兴趣的文章
细读shell-6
查看>>
ubuntu11.10安装php mysql wordpress
查看>>
一、2 基于wsgiref定义自己的web框架
查看>>
Ubuntu Server14.04 32位安装odoo8.0简单方法
查看>>
jQuery-easyui下的多表关联的增删改操作
查看>>
我的友情链接
查看>>
兼容IE,Firefox,CSS3 opacity透明度
查看>>
读取Hive中所有表的表结构,并在新Hive库中创建表,索引等
查看>>
XenServer部署系列之02——系统安装及许可
查看>>
linux下FTP服务器搭建
查看>>
程序的查询 ps - 笔记1
查看>>
Conversion to Dalvik format failed with error 1的又一种情形
查看>>
nodejs抓取数据二(列表解析)
查看>>
TextView中实现可点击链接的显示
查看>>
HAOI 树上操作
查看>>
深刻理解Python中的元类(metaclass)以及元类实现单例模式
查看>>
java随机生成n个不相同的整数
查看>>
DIV+CSS基础
查看>>
使用JS完成首页定时弹出广告图片
查看>>
codeforces 500c New Year Book Reading 【思维】
查看>>