tween.js缓动补间动画算法示例

作者:李俊杰 时间:2024-05-21 10:13:40 

一、理解tween.js

如果看到上面的已经理解了,可以跳过下面的部分.下面为对Tween.js的解释 下面就介绍如何使用这个Tween了,首先b、c、d三个参数(即初始值,变化量,持续时间)在缓动开始前,是需要先确定好的。 首先引入一个概念就补间动画 Flash做动画时会用到Tween类,利用它可以做很多动画效果,例如缓动、弹簧等等。 tween.js在Flash中可以解释为补间动画. 那么问题来了,什么是补间动画呢?

相信学过Flash的都知道补间动画是flash主要的非常重要的表现手段之一.补间动画有动作补间动画与形状补间动画两种,但是在js中却不需要了解这么多. 好了,废话不多说,先看看百度百科关于补间动画给出的定义: 补间动画:做flas * 时,在两个关键帧中间需要做“补间动画”,才能实现图画的运动; 插入补间动画后两个关键帧之间的插补帧是由计算机自动运算而得到的

那么什么是关键帧呢? 举个栗子: 先科普一下,平常所看的电影,动画都是24帧的,24帧为一秒.在人眼可以捕捉的范围内.可以想象两个点之间有有22个点,形成一条直线或者曲线.而每一个点就代表一帧,帧——就是动画中最小单位的单幅影像画面,而单幅影像画面就可以看做是一个对象(一切皆对象,除去值类型)了.而这条线就代表对象的运动轨迹.

二、四个参数

  1. t: current time-->代表第一个点,也就是第一帧,也就是一个动画开始的地方。

  2. b: beginning value-->代表初始值,也就是开始量,我们看电影或者动画一般都不会看序幕把,那么跳过开头部分,选择第一帧和最后一帧之间你要开始看位置,而此位置就是初始值。

  3. c: change in value-->代表的就是最后一帧减去初始值就是变化量,

  4. d: duration-->代表最后一帧,1s的结束,也是动画的结束。

tween.js的使用 1.下载 2.引入 3.使用tween.js语法

Tween.缓动函数名.缓动效果名(t,b,c,d);

注意:当开始步数增加到与结束步数相等时,整个运动结束. 注注意:只有当t增加到与d相等时才会结束运动;如果不等,运动不会停止.

三、tween文件代码


/*
* Tween.js
* t: current time(当前时间);
* b: beginning value(初始值);
* c: change in value(变化量);
* d: duration(持续时间)。
*/
var Tween = {
 Linear: function(t, b, c, d) { //匀速
   return c * t / d + b;
 },
 Quad: { //二次方缓动效果
   easeIn: function(t, b, c, d) {
     return c * (t /= d) * t + b;
   },
   easeOut: function(t, b, c, d) {
     return -c *(t /= d)*(t-2) + b;
   },
   easeInOut: function(t, b, c, d) {
     if ((t /= d / 2) < 1) return c / 2 * t * t + b;
     return -c / 2 * ((--t) * (t-2) - 1) + b;
   }
 },
 Cubic: { //三次方缓动效果
   easeIn: function(t, b, c, d) {
     return c * (t /= d) * t * t + b;
   },
   easeOut: function(t, b, c, d) {
     return c * ((t = t/d - 1) * t * t + 1) + b;
   },
   easeInOut: function(t, b, c, d) {
     if ((t /= d / 2) < 1) return c / 2 * t * t*t + b;
     return c / 2*((t -= 2) * t * t + 2) + b;
   }
 },
 Quart: { //四次方缓动效果
   easeIn: function(t, b, c, d) {
     return c * (t /= d) * t * t*t + b;
   },
   easeOut: function(t, b, c, d) {
     return -c * ((t = t/d - 1) * t * t*t - 1) + b;
   },
   easeInOut: function(t, b, c, d) {
     if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
     return -c / 2 * ((t -= 2) * t * t*t - 2) + b;
   }
 },
 Quint: { //五次方缓动效果
   easeIn: function(t, b, c, d) {
     return c * (t /= d) * t * t * t * t + b;
   },
   easeOut: function(t, b, c, d) {
     return c * ((t = t/d - 1) * t * t * t * t + 1) + b;
   },
   easeInOut: function(t, b, c, d) {
     if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
     return c / 2*((t -= 2) * t * t * t * t + 2) + b;
   }
 },
 Sine: { //正弦缓动效果
   easeIn: function(t, b, c, d) {
     return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
   },
   easeOut: function(t, b, c, d) {
     return c * Math.sin(t/d * (Math.PI/2)) + b;
   },
   easeInOut: function(t, b, c, d) {
     return -c / 2 * (Math.cos(Math.PI * t/d) - 1) + b;
   }
 },
 Expo: { //指数缓动效果
   easeIn: function(t, b, c, d) {
     return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
   },
   easeOut: function(t, b, c, d) {
     return (t==d) ? b + c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
   },
   easeInOut: function(t, b, c, d) {
     if (t==0) return b;
     if (t==d) return b+c;
     if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
     return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
   }
 },
 Circ: { //圆形缓动函数
   easeIn: function(t, b, c, d) {
     return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
   },
   easeOut: function(t, b, c, d) {
     return c * Math.sqrt(1 - (t = t/d - 1) * t) + b;
   },
   easeInOut: function(t, b, c, d) {
     if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
     return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
   }
 },
 Elastic: { //指数衰减正弦曲线缓动函数
   easeIn: function(t, b, c, d, a, p) { //加速
     var s;
     if (t==0) return b;
     if ((t /= d) == 1) return b + c;
     if (typeof p == "undefined") p = d * .3;
     if (!a || a < Math.abs(c)) {
       s = p / 4;
       a = c;
     } else {
       s = p / (2 * Math.PI) * Math.asin(c / a);
     }
     return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
   },
   easeOut: function(t, b, c, d, a, p) { //减速
     var s;
     if (t==0) return b;
     if ((t /= d) == 1) return b + c;
     if (typeof p == "undefined") p = d * .3;
     if (!a || a < Math.abs(c)) {
       a = c;
       s = p / 4;
     } else {
       s = p/(2*Math.PI) * Math.asin(c/a);
     }
     return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
   },
   easeInOut: function(t, b, c, d, a, p) { //先加速后减速
     var s;
     if (t==0) return b;
     if ((t /= d / 2) == 2) return b+c;
     if (typeof p == "undefined") p = d * (.3 * 1.5);
     if (!a || a < Math.abs(c)) {
       a = c;
       s = p / 4;
     } else {
       s = p / (2 *Math.PI) * Math.asin(c / a);
     }
     if (t < 1) return -.5 * (a * Math.pow(2, 10* (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
     return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;
   }
 },
 Back: { //超过范围的三次方的缓动函数
   easeIn: function(t, b, c, d, s) {
     if (typeof s == "undefined") s = 1.70158;
     return c * (t /= d) * t * ((s + 1) * t - s) + b;
   },
   easeOut: function(t, b, c, d, s) {
     if (typeof s == "undefined") s = 1.70158;
     return c * ((t = t/d - 1) * t * ((s + 1) * t + s) + 1) + b;
   },
   easeInOut: function(t, b, c, d, s) {
     if (typeof s == "undefined") s = 1.70158;
     if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
     return c / 2*((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
   }
 },
 Bounce: { //指数衰减的反弹曲线缓动函数
   easeIn: function(t, b, c, d) {
     return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b;
   },
   easeOut: function(t, b, c, d) {
     if ((t /= d) < (1 / 2.75)) {
       return c * (7.5625 * t * t) + b;
     } else if (t < (2 / 2.75)) {
       return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
     } else if (t < (2.5 / 2.75)) {
       return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
     } else {
       return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
     }
   },
   easeInOut: function(t, b, c, d) {
     if (t < d / 2) {
       return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
     } else {
       return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
     }
   }
 }
}
Math.tween = Tween;

四、举个栗子


<!DOCTYPE html>
<html>

<head>
   <meta charset="UTF-8">
   <title></title>
   <script src="https://cdn.jsdelivr.net/npm/vue"></script>
   <script src="Tween/tween.js"></script>
   <style>
     *{margin: 0;padding: 0;}
     .out{width: 800px;height: 500px;background: #e5e5e5;position: relative;padding: 20px;text-align: center;}
     .inner{width: 50px;height: 50px;border-radius: 50%;background: #FF0000; position: absolute;left: 50px;top: 50px;}
   </style>
 </head>

<body>
   <div id="app" class="out">
     <div class="inner" id="ball"></div>
     <button id="start" @click="start()">start</button>
   </div>
 </body>
 <script type="text/javascript">
   var app = new Vue({
     el: '#app',
     data: {
       t: 0,
       b: 50,
       c: 500,
       d: 1500,
     },
     methods:{
       start(){
         var t = this.t;
         const b = this.b;
         const c = this.c;
         const d = this.d;
         const setInt = setInterval(()=>{
           t++;
           console.log(t)
           if(t==300){clearInterval(setInt)}
           console.log(t);
           const ballLeft = Tween.Linear(t,b,c,d)+"px";
           ball.style.left = ballLeft;
         },20)
       }
     }
   })
 </script>
</html>

五、个人体会

tween的优势在于tween实现效果是依据算法,不是某种语言的语法,因此可以运用的地方很广泛,一次学习终身受益。

来源:https://segmentfault.com/a/1190000013272336

标签:tween.js,缓动
0
投稿

猜你喜欢

  • SQLServer中临时表与表变量的区别分析

    2024-01-22 22:44:18
  • python3利用Socket实现通信的方法示例

    2022-04-10 03:09:04
  • mysql中合并两个字段的方法分享

    2024-01-21 19:01:44
  • Python实现读取文件夹按数字排序功能

    2023-08-24 02:12:45
  • 详解python之简单主机批量管理工具

    2023-04-24 07:45:44
  • Python使用列表和字典实现简单的考试系统详解

    2023-11-07 11:14:53
  • Python 模拟购物车的实例讲解

    2021-01-13 05:24:08
  • asp分类算法要解决的问题

    2009-09-10 16:49:00
  • Python文件的操作处理详解

    2022-07-07 06:44:16
  • Vue父组件和子组件之间数据传递和方法调用

    2023-07-02 17:01:57
  • python中id函数运行方式

    2021-12-27 14:03:50
  • Python Web框架之Django框架Model基础详解

    2023-11-04 22:07:00
  • python中heapq堆排算法的实现

    2022-10-13 23:11:40
  • Python中非常好用的内置函数详解

    2023-04-05 06:28:25
  • 详解使用vue实现tab 切换操作

    2023-07-02 17:06:39
  • 链接与文本标签们

    2008-04-04 18:07:00
  • 在Python的Flask中使用WTForms表单框架的基础教程

    2023-05-10 05:20:08
  • Python松散正则表达式用法分析

    2021-03-12 02:51:36
  • Python使用Opencv打开笔记本电脑摄像头报错解问题及解决

    2022-12-02 10:32:01
  • 解决sql server保存对象字符串转换成uniqueidentifier失败的问题

    2024-01-20 01:22:59
  • asp之家 网络编程 m.aspxhome.com