软件项目技术点(1)——Tween算法及缓动效果
AxeSlide软件项目梳理 canvas绘图系列知识点整理
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 }