var Tween={
Linear:function(t,b,c,d){
return c*t/d+b;
},
QuadIn:function(t,b,c,d){
return c*(t/=d)*t+b;
},
QuadOut:function(t,b,c,d){
return -c*(t/=d)*(t-2)+b;
},
QuadInOut:function(t,b,c,d){
if((t/=d/2)<1) return c/2*t*t+b;
return -c/2*((--t)*(t-2)-1)+b;
},
CubicIn:function(t,b,c,d){
return c*(t/=d)*t*t+b;
}
放眼望去,基本都是靠 t, b, c, d 四个参数来控制曲线,先搞清楚四个参数的含义。
t ----初始时间 b ----起始位置 c ----移动的距离 d ----缓动执行多长时间
用最基础的线性公式自己琢磨一下吧:
Linear:function(t,b,c,d){
return c*t/d+b;
}
根据 return,b 应该是初始位置,t / d 是动画完成百分比,d 是总动画时长,t 是已经运行动画时长,c 是总移动距离(状态),目的位置(状态)= b + c 。
参数里 b, c, d (初始位置,目的位置 - 初始位置, 动画时长)是一开始设定好的,在运行过程中不变,只有 t 是随着时间变化,让函数返回不同的值,这个值,就是变化状态的百分比值。例如,物体从 x=20 移动到 x = 100,物体当前 x = 20 + (100 - 20) * 返回值。
开始分析 CubicOut 公式:
return c*((t=t/d-1)*t*t + 1) + b;
公式里面 t 还有一个赋值运算,所以公式实际上是这样子的
t=t/d-1;return c*(t*t*t+1)+b;
经过赋值计算的 t ,实际上已经跟真正的 t (已运行动画时长)没什么关系了,赋值后的 "t" 其实是 “负动画剩余时间百分比”,下文加引号的 "t" 指的都是赋值之后的 t。
举个数值来带入,假设动画总时长 d = 1,初始位置 b = 0,移动距离 c = 1,动画运行时间为 t = 0.1,
先带入 Linear:c * t / d + b ==> 1 * 0.1 / 1 + 0 = 0.1;
再带入 Cubic:t = t / d - 1 ==> t = -0.9;
c * (t * t * t + 1) + b ==> 1 * (-0.9 * -0.9 * -0.9 + 1) + 0 = 1 - 0.729 = 0.271;
Cubic 比 Linear 初速度更快,符合预期,现在把 0.1 时间间隔的位置计算并代入一下看看:
Cubic 曲线和生成的点契合,公式没问题(不知道啥 gif 这么卡)。
Cubic 立方曲线顾名思义,公式里 "t" 进行了三次相乘。
那 Quad 就是两个 "t" 相乘:
t = t / d - 1;
return c * (t * t + 1) + b;
代入图形看一下:
代入公式生成的点都飞出画面了,原来因为 "t" 是一个负数, t3< 0,但是 t2> 0,所以飞上去了。
公式调整一下:t=t/d-1;return c*(-t*t+1)+b;
正常了,所以遇到偶数次方公式,"t" 乘积前加个 "-" 就好。
有个疑问,公式调整一下,保证每次 "t" > 0,不是更方便么,像这样:
t = 1 - t / d;
return c * (1 - t * t) + b;
现在用“推导”的 Quad 公式和 Tween.js 里的 Quad 公式对比一下:
t=1-t/d;
return c*(1-t*t)+b;
...
return c*(1-(1-t/ d) * (1 - t /d))+b;
...
return c*(1-(1+(t/ d) * (t /d)-2*t/d))+b;
...
return c*(1-1-(t/ d) * (t /d)+2*t/d)+b;
...
return c*(-(t/ d) * (t /d)+2*t/d)+b;
...
return -c*((t/ d) * (t /d)-2*t/d)+b;
...
return -c*((t/ d - 2) * (t /d))+b;
...
return -c*(t/=d)*(t-2)+b;
...
return -c*(t/d)*(t/d-2)+b;
两个公式是相等的,完毕。
Quad 二次、Cubic 三次、Quart 四次、Quint 五次同理,都可以用:
t=1-t/d; return c*(1-Math.pow(t,n))+b; //n=几次
网友评论