Tween算法及缓动效果
软件里在切换步序时需要有过渡动画效果,从当前位置的画面缓动到目标位置的画面。动画效果可重新查看文章系列第一篇《AxeSlide软件项目梳理》中的作品展示动画。
实例效果:
Tween类型:
ease类型:
效果说明:
Linear:无缓动效果;
Quadratic:二次方的缓动(t^2);
Cubic:三次方的缓动(t^3);
Quartic:四次方的缓动(t^4);
Quintic:五次方的缓动(t^5);
Sinusoidal:正弦曲线的缓动(sin(t));
Exponential:指数曲线的缓动(2^t);
Circular:圆形曲线的缓动(sqrt(1-t^2));
Elastic:指数衰减的正弦曲线缓动;
Back:超过范围的三次方缓动((s+1)*t^3 - s*t^2);
Bounce:指数衰减的反弹缓动。
ps:以上都是自己的烂翻译,希望各位修正。
每个效果都分三个缓动方式(方法),分别是:
easeIn:从0开始加速的缓动;
easeOut:减速到0的缓动;
easeInOut:前半段从0开始加速,后半段减速到0的缓动。
其中Linear是无缓动效果,没有以上效果。
参数及使用示例:
Tween中的方法接受4个参数t,b,c,d 。返回值为计算后的当前位置。
四个参数分别是:
t: current time(当前时间);
b: beginning value(初始值);
c: change in value(变化量);
d: duration(持续时间)。
比如: 希望top从100px到150px,在500ms内完成
1 var easeInQuad = function (x, t, b, c, d) {
2 return c*(t/=d)*t + b;
3 },
4
5 var d = 500,b = 100,c = 150 - b;
6 var count = d / 20; //500毫秒分多少次执行完毕
7 setInterval(function(){
8 var x = easeInQuad(0, d - (count-- * 20) , b, c, d);
9 //return 的结果便是每个时间片,top的值
10 }, 20);
11 //一般浏览器的timer最小是20(这是windows底层的CPU时间决定的!)
Tween完整算法代码
1 export class Tween{
2 static Linear = function (t, b, c, d) { return c * t / d + b; };
3 static Quad = {
4 easeIn: function (t, b, c, d) {
5 return c * (t /= d) * t + b;
6 },
7 easeOut: function (t, b, c, d) {
8 return -c * (t /= d) * (t - 2) + b;
9 },
10 easeInOut: function (t, b, c, d) {
11 if ((t /= d / 2) < 1) return c / 2 * t * t + b;
12 return -c / 2 * ((--t) * (t - 2) - 1) + b;
13 }
14 };
15 static Cubic = {
16 easeIn: function (t, b, c, d) {
17 return c * (t /= d) * t * t + b;
18 },
19 easeOut: function (t, b, c, d) {
20 return c * ((t = t / d - 1) * t * t + 1) + b;
21 },
22 easeInOut: function (t, b, c, d) {
23 if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
24 return c / 2 * ((t -= 2) * t * t + 2) + b;
25 }
26 };
27 static Quart = {
28 easeIn: function (t, b, c, d) {
29 return c * (t /= d) * t * t * t + b;
30 },
31 easeOut: function (t, b, c, d) {
32 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
33 },
34 easeInOut: function (t, b, c, d) {
35 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
36 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
37 }
38 };
39 static Quint = {
40 easeIn: function (t, b, c, d) {
41 return c * (t /= d) * t * t * t * t + b;
42 },
43 easeOut: function (t, b, c, d) {
44 return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
45 },
46 easeInOut: function (t, b, c, d) {
47 if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
48 return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
49 }
50 };
51 static Sine = {
52 easeIn: function (t, b, c, d) {
53 return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
54 },
55 easeOut: function (t, b, c, d) {
56 return c * Math.sin(t / d * (Math.PI / 2)) + b;
57 },
58 easeInOut: function (t, b, c, d) {
59 return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
60 }
61 };
62 static Expo = {
63 easeIn: function (t, b, c, d) {
64 return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
65 },
66 easeOut: function (t, b, c, d) {
67 return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
68 },
69 easeInOut: function (t, b, c, d) {
70 if (t == 0) return b;
71 if (t == d) return b + c;
72 if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
73 return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
74 }
75 };
76 static Circ = {
77 easeIn: function (t, b, c, d) {
78 return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
79 },
80 easeOut: function (t, b, c, d) {
81 return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
82 },
83 easeInOut: function (t, b, c, d) {
84 if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
85 return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
86 }
87 };
88 static Elastic = {
89 easeIn: function (t, b, c, d, a, p) {
90 var s;
91 if (t == 0) return b;
92 if ((t /= d) == 1) return b + c;
93 if (typeof p == "undefined") p = d * .3;
94 if (!a || a < Math.abs(c)) {
95 s = p / 4;
96 a = c;
97 } else {
98 s = p / (2 * Math.PI) * Math.asin(c / a);
99 }
100 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
101 },
102 easeOut: function (t, b, c, d, a, p) {
103 var s;
104 if (t == 0) return b;
105 if ((t /= d) == 1) return b + c;
106 if (typeof p == "undefined") p = d * .3;
107 if (!a || a < Math.abs(c)) {
108 a = c;
109 s = p / 4;
110 } else {
111 s = p / (2 * Math.PI) * Math.asin(c / a);
112 }
113 return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
114 },
115 easeInOut: function (t, b, c, d, a, p) {
116 var s;
117 if (t == 0) return b;
118 if ((t /= d / 2) == 2) return b + c;
119 if (typeof p == "undefined") p = d * (.3 * 1.5);
120 if (!a || a < Math.abs(c)) {
121 a = c;
122 s = p / 4;
123 } else {
124 s = p / (2 * Math.PI) * Math.asin(c / a);
125 }
126 if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
127 return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
128 }
129 };
130 static Back = {
131 easeIn: function (t, b, c, d, s) {
132 if (typeof s == "undefined") s = 1.70158;
133 return c * (t /= d) * t * ((s + 1) * t - s) + b;
134 },
135 easeOut: function (t, b, c, d, s) {
136 if (typeof s == "undefined") s = 1.70158;
137 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
138 },
139 easeInOut: function (t, b, c, d, s) {
140 if (typeof s == "undefined") s = 1.70158;
141 if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
142 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
143 }
144 };
145 static Bounce = {
146 easeIn: function (t, b, c, d) {
147 return c - Animation.Bounce.easeOut(d - t, 0, c, d) + b;
148 },
149 easeOut: function (t, b, c, d) {
150 if ((t /= d) < (1 / 2.75)) {
151 return c * (7.5625 * t * t) + b;
152 } else if (t < (2 / 2.75)) {
153 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
154 } else if (t < (2.5 / 2.75)) {
155 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
156 } else {
157 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
158 }
159 },
160 easeInOut: function (t, b, c, d) {
161 if (t < d / 2) {
162 return Animation.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
163 } else {
164 return Animation.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
165 }
166 }
167 }
168 }