前言

缓动在动画效果中应用非常广泛,在合适的时候使用一些缓动效果会使得效果更加符合人的直观感受,简单来说,会显得更加自然。

WPF提供了11种缓动效果,涵盖了大部分的使用场景。不过如果需要在非WPF下使用这些缓动效果,就需要知道对应的曲线公式了。因为公式是通用的,所以可以很轻松的使用其他语言实现。

由于本人数学水平有限,所以本文注重的应用而不是原理。在本文中,将会使用C#去实现,并附上与WPF原版的对比效果。

本文参考:

1,https://docs.microsoft.com/zh-cn/dotnet/desktop/wpf/graphics-multimedia/easing-functions?view=netframeworkdesktop-4.8

2,https://github.com/ai/easings.net

文末会附上示例源代码,需要者可自行下载。

本文地址:https://www.cnblogs.com/lesliexin/p/13594811.html


一、WPF中的缓动效果

在WPF中,共有11种:Back,Bounce,Circle,Quadratic,Cubic,Quartic,Quintic,Elastic,Exponential,Sine,Power。不过严格来说只有7种,因为Quadratic,Cubic,Quartic,Quintic是由Power去实现的,由于Power参数未定,所以仅实现前10种效果。

所以对于每个缓动效果而言,都有三种模式:缓入(EaseIn)、缓出(EaseOut)、缓入缓出(EaseInOut)。


二、公式与动画

一个元素的动画效果,其实就是这个元素变化的快慢,也就是速度。速度与时间间隔和该时间间隔内运动距离两个变量有关。在实际实现中,时间间隔是相等的,那么速度的变化与距离的变化就成正比。在一个二维坐标当中,横坐标为时间,纵坐标为距离,那么其形成的曲线中,曲线越陡,速度越快,曲线越平缓,则速度越慢。

而我们使用公式的目的,就是取得这个纵坐标的值。

不过,要注意的是,我们获取的曲线的时间范围是:0~1,这不是具体的1秒或1毫秒,而是“单位1”。举例来说,如果一个动画效果时长是2000ms,那么在第x ms时,对应的单位时间就是x/2000。


三、缓动公式、缓动效果、与WPF对比

1,Back

曲线(图源自MSDN):

1.1,曲线公式

public static double Back(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return 2.70158 * x * x * x - 1.70158 * x * x;
case LEaseMode.EaseOut:
return 1 + 2.70158 * Math.Pow(x - 1, 3) + 1.70158 * Math.Pow(x - 1, 2);
case LEaseMode.EaseInOut:
return x < 0.5 ? (Math.Pow(2 * x, 2) * (7.189819 * x - 2.5949095)) / 2 : (Math.Pow(2 * x - 2, 2) * (7.189819 * x - 4.5949095) + 2) / 2;
default:
return 0;
}
}

Back

1.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

1.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

2,Bounce

曲线(图源自MSDN):

2.1,曲线公式

private static double BounceOut(double x)
{
if (x < 1d / 2.75d) return 7.5625 * x * x;
else if (x < 2d / 2.75d) return 7.5625 * (x -= 1.5d / 2.75d) * x + 0.75;
else if(x<2.5d/2.75d) return 7.5625 * (x -= 2.25d / 2.75d) * x + 0.9375;
else return 7.5625 * (x -= 2.625d / 2.75d) * x + 0.984375;
} public static double Bounce(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return 1 - BounceOut(1 - x);
case LEaseMode.EaseOut:
return BounceOut(x);
case LEaseMode.EaseInOut:
return x < 0.5 ? (1 - BounceOut(1 - 2 * x)) / 2 : (1 + BounceOut(2 * x - 1)) / 2;
default:
return 0;
}
}

Bounce

2.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

2.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

3,Circle

曲线(图源自MSDN):

3.1,曲线公式

public static double Circle(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return 1 - Math.Sqrt(1 - Math.Pow(x, 2));
case LEaseMode.EaseOut:
return Math.Sqrt(1 - Math.Pow(x - 1, 2));
case LEaseMode.EaseInOut:
return x < 0.5 ? (1 - Math.Sqrt(1 - Math.Pow(2 * x, 2))) / 2 : (Math.Sqrt(1 - Math.Pow(-2 * x + 2, 2)) + 1) / 2;
default:
return 0;
}
}

Circle

3.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

3.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

4,Quadratic

曲线(图源自MSDN):

4.1,曲线公式

public static double Power(double x,LEaseMode easeMode,int power)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return Math.Pow(x, power);
case LEaseMode.EaseOut:
return 1-Math.Pow(1-x,power);
case LEaseMode.EaseInOut:
return x < 0.5 ? Math.Pow(2,power-1)*Math.Pow(x,power) : 1 - Math.Pow(-2 * x + 2, power) / 2;
default:
return 0;
}
} public static double Quadratic(double x, LEaseMode easeMode)
{
return Power(x, easeMode, 2);
}

Quadratic

4.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

4.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

5,Cubic

曲线(图源自MSDN):

5.1,曲线公式

public static double Power(double x,LEaseMode easeMode,int power)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return Math.Pow(x, power);
case LEaseMode.EaseOut:
return 1-Math.Pow(1-x,power);
case LEaseMode.EaseInOut:
return x < 0.5 ? Math.Pow(2,power-1)*Math.Pow(x,power) : 1 - Math.Pow(-2 * x + 2, power) / 2;
default:
return 0;
}
} public static double Cubic(double x, LEaseMode easeMode)
{
return Power(x, easeMode, 3);
}

Cubic

5.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

5.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

6,Quartic

曲线(图源自MSDN):

6.1,曲线公式

public static double Power(double x,LEaseMode easeMode,int power)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return Math.Pow(x, power);
case LEaseMode.EaseOut:
return 1-Math.Pow(1-x,power);
case LEaseMode.EaseInOut:
return x < 0.5 ? Math.Pow(2,power-1)*Math.Pow(x,power) : 1 - Math.Pow(-2 * x + 2, power) / 2;
default:
return 0;
}
} public static double Quartic(double x, LEaseMode easeMode)
{
return Power(x, easeMode,4);
}

Quartic

6.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

6.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

7,Quintic

曲线(图源自MSDN):

7.1,曲线公式

public static double Power(double x,LEaseMode easeMode,int power)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return Math.Pow(x, power);
case LEaseMode.EaseOut:
return 1-Math.Pow(1-x,power);
case LEaseMode.EaseInOut:
return x < 0.5 ? Math.Pow(2,power-1)*Math.Pow(x,power) : 1 - Math.Pow(-2 * x + 2, power) / 2;
default:
return 0;
}
} public static double Quintic(double x, LEaseMode easeMode)
{
return Power(x, easeMode, 5);
}

Quintic

7.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

7.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

8,Elastic

曲线(图源自MSDN):

8.1,曲线公式

public static double Elastic(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return x == 0 ? 0 : x == 1 ? 1 : -Math.Pow(2, 10 * x - 10) * Math.Sin((x * 10 - 10.75) * 2 * Math.PI / 3);
case LEaseMode.EaseOut:
return x == 0 ? 0 : x == 1 ? 1 : Math.Pow(2, -10 * x) * Math.Sin((x * 10 - 0.75) * 2 * Math.PI / 3)+1;
case LEaseMode.EaseInOut:
return x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? -(Math.Pow(2, 20 * x - 10) * Math.Sin((x * 20 - 11.125) * 2 * Math.PI / 4.5)) / 2 : (Math.Pow(2, -20 * x + 10) * Math.Sin((x * 20 - 11.125) * 2 * Math.PI / 4.5)) / 2 + 1;
default:
return 0;
}
}

Elastic

8.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

8.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

9,Exponential

曲线(图源自MSDN):

9.1,曲线公式

public static double Exponential(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return x == 0 ? 0 : Math.Pow(2, 10 * x - 10);
case LEaseMode.EaseOut:
return x == 1 ? 1 : 1 - Math.Pow(2, -10 * x);
case LEaseMode.EaseInOut:
return x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? Math.Pow(2, 20 * x - 10) / 2 : (2 - Math.Pow(2, -20 * x + 10)) / 2;
default:
return 0;
}
}

Exponential

9.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

9.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:

10,Sine

曲线(图源自MSDN):

10.1,曲线公式

public static double Sine(double x, LEaseMode easeMode)
{
switch (easeMode)
{
case LEaseMode.EaseIn:
return 1 - Math.Cos((x * Math.PI) / 2);
case LEaseMode.EaseOut:
return Math.Sin((x * Math.PI) / 2);
case LEaseMode.EaseInOut:
return -(Math.Cos(Math.PI * x) - 1) / 2;
default:
return 0;
}
}

Sine

10.2,WinForm效果

a,EaseIn:

b,EaseOut:

c,EaseInOut:

10.3,WPF效果

(上面矩形为WPF原版缓动效果,下面矩形为公式实现效果)

a,EaseIn:

b,EaseOut:

c,EaseInOut:


四、结束语

通过上面的动图我们会发现,其中一些效果,使用公式生成的与WPF原版的是不一样的,一是因为WPF原版的曲线不是固定的,还有其他参数去调控,而我对比的时候使用的是WPF默认的缓动效果;二是因为一像Bounce、Elastic等曲线以我的能力很难扒出来具体的公式,所以更多的是依照文首的Github上那个项目中的公式。所以难免有所差异。

同时,写本篇文章是因为在之后的自定义控件系列文章,以及其他涉及图形的文章中,会频繁的使用缓动效果以增强直观感受,到时文章中会引用本文所生成的类库,当然也会随文附上缓动公式。


五、源代码下载

源代码包含:

1,缓动类库

2,WinForm演示

3,WPF演示

https://files.cnblogs.com/files/lesliexin/LEase.7z

缓动公式整理(附:C#实现及WPF原版对比)的更多相关文章

  1. css3 缓动公式

    var easingMap = { "linear": [0.250, 0.250, 0.750, 0.750], "ease": [0.250, 0.100, ...

  2. javascript的缓动效果

    这部分对原先的缓动函数进行抽象化,并结合缓动公式进行强化.成品的效果非常惊人逆天.走过路过不要错过. 好了,打诨到此为止.普通的加速减速是难以让人满意的,为了实现弹簧等让人眼花缭乱的效果必须动用缓动公 ...

  3. 缓动动画(json)

    function animate(obj, json){ clearInterval(obj.timer); obj.timer=setInterval(function(){ var flag = ...

  4. javascript 45种缓动效果BY司徒正美

    javascript 45种缓动效果 参数 类型 说明 el element 必需,为页面元素 begin number 必需,开始的位置 change number 必需,要移动的距离 durati ...

  5. jQuery-1.9.1源码分析系列(十五) 动画处理——缓动动画核心Tween

    在jQuery内部函数Animation中调用到了createTweens()来创建缓动动画组,创建完成后的结果为: 可以看到上面的缓动动画组有四个原子动画组成.每一个原子动画的信息都包含在里面了. ...

  6. 利用tween.js算法生成缓动效果

    在讲tween类之前,不得不提的是贝塞尔曲线了.首先,贝塞尔曲线是指依据四个位置任意的点坐标绘制出的一条光滑曲线.它在作图工具或动画中中运用得比较多,例如PS中的钢笔工具,firework中的画笔等等 ...

  7. Silverlight动画学习笔记(三):缓动函数

    (一)定义: 缓动函数:可以将自定义算术公式应用于动画 (二)为什么要用缓动函数: 您可能希望某一对象逼真地弹回或其行为像弹簧一样.您可以使用关键帧动画甚至 From/To/By 动画来大致模拟这些效 ...

  8. JS基础知识——缓动动画

    基于距离的缓动动画 原理:设定起始位置  start 和终止位置 end,变化会越来越慢. 公式:start=start+(end-start)/10;     这个10不是固定的,想分成多少份就分成 ...

  9. JS实现缓动动画效果

    原理如下: 假设要从数值A变化到数值B,如果是线性运动,则每次移动距离是一样:如果是缓动,每次移动距离不一样.那如何才能不一样呢?很简单,按比例移动就可以. 例如:每次移动剩余距离的一半. 对吧,超容 ...

随机推荐

  1. 安装centos7显示器分辨率不适配的解决方法

    1,系统读取安装信息后,选择Install Centos7 然后Tab调出参数行 2,在quiet后空格输入nomodeset回车即可

  2. onlyoffice在线编辑

    一.安装ONLYOFFICE Document Server 二.集成onlyoffice的二次开发 三.故障排除: 四.缺陷 五.总结 ONLYOFFICE Document Server提供文档协 ...

  3. CentOS7上lvm分区调整(resize2fs: Bad magic number in super-block while trying to open ...)

    问题描述:根目录空间占用率100% 首先用传统resize2fs方式调整分区: resize2fs -p /dev/mapper/centos-home 50Gresize2fs 1.42.9 (28 ...

  4. 第5篇 Scrum 冲刺博客

    1.站立会议 照骗 进度 成员 昨日完成任务 今日计划任务 遇到的困难 钟智锋 完成技能 完全重构游戏逻辑代码,并编写调试模块 队友的代码已经和想法相去甚远 庄诗楷 制作了开始游戏的界面 进行了相关的 ...

  5. shell 三剑客之 sed

    sed 在shell 编程里也很常用,功能强大! 同grep一样,sed提供两种方式: 方式一:stdout | sed [option] "pattern command" 从文 ...

  6. oracle再回首

    第一章 Oracle 数据库的使用   一. 数据库相关概念   1 什么是数据库 所谓的数据库其实就是数据的集合.用户可以对集合中的数据进行新增.查询.更新. 删除等操作.数据库是以一定方式储存在一 ...

  7. Unity CommandLine

    CommandLineArguments https://docs.unity3d.com/Manual/CommandLineArguments.html Unity3D游戏开发之“unity3D命 ...

  8. Python 中的数字到底是什么?

    花下猫语:在 Python 中,不同类型的数字可以直接做算术运算,并不需要作显式的类型转换.但是,它的"隐式类型转换"可能跟其它语言不同,因为 Python 中的数字是一种特殊的对 ...

  9. three.js尝试(一)模拟演唱会效果

    工作闲暇之余,偶然翻到了Three.js的官网,立刻被它酷炫的案例给惊艳到了,当即下定决心要试验摸索一番,于是看demo,尝试,踩坑,解决问题,终于搞定了,一个模拟演唱会场景. 主角围绕一个钢管在舞动 ...

  10. 《神经网络的梯度推导与代码验证》之LSTM的前向传播和反向梯度推导

    前言 在本篇章,我们将专门针对LSTM这种网络结构进行前向传播介绍和反向梯度推导. 关于LSTM的梯度推导,这一块确实挺不好掌握,原因有: 一些经典的deep learning 教程,例如花书缺乏相关 ...