tween 緩動動畫
在講tween類之前,不得不提的是貝塞爾曲線了。首先,貝塞爾曲線是指依據四個位置任意的點座標繪製出的一條光滑曲線。它在作圖工具或動畫中中運用得比較多,例如PS中的鋼筆工具,firework中的畫筆等等。無論運用在哪裡,它們的原理都是一樣的。同樣,在用js實現運動效果時,我們也可以利用貝塞爾曲線來實現不同的特效,而tween.js就是一個封裝好的計算輔助演算法。你可以通過連續輸入多個值,然後利用貝塞爾曲線公式輸出不同的值,最終形成了一條光滑的曲線。因為一條曲線上的值的不一樣的,所以我們可以利用曲線的特性創造出不同的效果。
tween.js封裝了多種效果的計算方法,我們可以利用裡面的公式或者自己重寫方法。以下是原始碼,可根據自己的需要增刪使用。
1 // Tween類 2 var Tween = { 3 Linear: function(t,b,c,d){ return c*t/d + b; }, 4 Quad: { 5 easeIn: function(t,b,c,d){ 6 return c*(t/=d)*t + b; 7 }, 8 easeOut: function(t,b,c,d){ 9 return -c *(t/=d)*(t-2) + b; 10 }, 11 easeInOut: function(t,b,c,d){ 12 if ((t/=d/2) < 1) return c/2*t*t + b; 13 return -c/2 * ((--t)*(t-2) - 1) + b; 14 } 15 }, 16 Cubic: { 17 easeIn: function(t,b,c,d){ 18 return c*(t/=d)*t*t + b; 19 }, 20 easeOut: function(t,b,c,d){ 21 return c*((t=t/d-1)*t*t + 1) + b; 22 }, 23 easeInOut: function(t,b,c,d){ 24 if ((t/=d/2) < 1) return c/2*t*t*t + b; 25 return c/2*((t-=2)*t*t + 2) + b; 26 } 27 }, 28 Quart: { 29 easeIn: function(t,b,c,d){ 30 return c*(t/=d)*t*t*t + b; 31 }, 32 easeOut: function(t,b,c,d){ 33 return -c * ((t=t/d-1)*t*t*t - 1) + b; 34 }, 35 easeInOut: function(t,b,c,d){ 36 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 37 return -c/2 * ((t-=2)*t*t*t - 2) + b; 38 } 39 }, 40 Quint: { 41 easeIn: function(t,b,c,d){ 42 return c*(t/=d)*t*t*t*t + b; 43 }, 44 easeOut: function(t,b,c,d){ 45 return c*((t=t/d-1)*t*t*t*t + 1) + b; 46 }, 47 easeInOut: function(t,b,c,d){ 48 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; 49 return c/2*((t-=2)*t*t*t*t + 2) + b; 50 } 51 }, 52 Sine: { 53 easeIn: function(t,b,c,d){ 54 return -c * Math.cos(t/d * (Math.PI/2)) + c + b; 55 }, 56 easeOut: function(t,b,c,d){ 57 return c * Math.sin(t/d * (Math.PI/2)) + b; 58 }, 59 easeInOut: function(t,b,c,d){ 60 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; 61 } 62 }, 63 Expo: { 64 easeIn: function(t,b,c,d){ 65 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; 66 }, 67 easeOut: function(t,b,c,d){ 68 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; 69 }, 70 easeInOut: function(t,b,c,d){ 71 if (t==0) return b; 72 if (t==d) return b+c; 73 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; 74 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; 75 } 76 }, 77 Circ: { 78 easeIn: function(t,b,c,d){ 79 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; 80 }, 81 easeOut: function(t,b,c,d){ 82 return c * Math.sqrt(1 - (t=t/d-1)*t) + b; 83 }, 84 easeInOut: function(t,b,c,d){ 85 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; 86 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; 87 } 88 }, 89 Elastic: { 90 easeIn: function(t,b,c,d,a,p){ 91 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 92 if (!a || a < Math.abs(c)) { a=c; var s=p/4; } 93 else var s = p/(2*Math.PI) * Math.asin (c/a); 94 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 95 }, 96 easeOut: function(t,b,c,d,a,p){ 97 if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; 98 if (!a || a < Math.abs(c)) { a=c; var s=p/4; } 99 else var s = p/(2*Math.PI) * Math.asin (c/a); 100 return (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b); 101 }, 102 easeInOut: function(t,b,c,d,a,p){ 103 if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); 104 if (!a || a < Math.abs(c)) { a=c; var s=p/4; } 105 else var s = p/(2*Math.PI) * Math.asin (c/a); 106 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 107 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; 108 } 109 }, 110 Back: { 111 easeIn: function(t,b,c,d,s){ 112 if (s == undefined) s = 1.70158; 113 return c*(t/=d)*t*((s+1)*t - s) + b; 114 }, 115 easeOut: function(t,b,c,d,s){ 116 if (s == undefined) s = 1.70158; 117 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 118 }, 119 easeInOut: function(t,b,c,d,s){ 120 if (s == undefined) s = 1.70158; 121 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 122 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 123 } 124 }, 125 Bounce: { 126 easeIn: function(t,b,c,d){ 127 return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b; 128 }, 129 easeOut: function(t,b,c,d){ 130 if ((t/=d) < (1/2.75)) { 131 return c*(7.5625*t*t) + b; 132 } else if (t < (2/2.75)) { 133 return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; 134 } else if (t < (2.5/2.75)) { 135 return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; 136 } else { 137 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; 138 } 139 }, 140 easeInOut: function(t,b,c,d){ 141 if (t < d/2) return Tween.Bounce.easeIn(t*2, 0, c, d) * .5 + b; 142 else return Tween.Bounce.easeOut(t*2-d, 0, c, d) * .5 + c*.5 + b; 143 } 144 } 145 };
下載地址:http://pan.baidu.com/s/1sjQdWQx
這個演算法可以用在很多地方,如果滾動條的移動,物塊的移動或各種漸變等等。今天我就用物塊移動demo的例子來講講這個輔助計算類怎麼用吧,首先我們得建立一個定時器或者函式,一下是我常用的方法。
1 //利用tween.js返回特殊值,生成不同效果 2 function tweenFn(obj,attr,value,endFn){ 3 var timer = null; 4 var start = 0; //開始位置 5 // var value = value //改變值大小 6 var t = 0; //從0步開始 7 var endT = 30; //結束步數 8 clearInterval(timer); 9 timer = setInterval(function(){ 10 t++; 11 if(t>endT){ 12 clearInterval(timer); 13 endFn && endFn();//回撥函式存在則返回 14 return; 15 }; 16 obj.style[attr] = Tween.Cubic.easeInOut(t,start,value,endT)+"px"; 17 },30); 18 }
函式說明:obj,繫結執行的物件;
attr,改變的屬性值;
value,改變值的大小;
endFn,執行完畢的回撥函式,沒有可不寫;
start,屬性初始值;
t,endT,執行的步數,可理解為分多少次執行完。
函式第十六行中Tween.Cubic.easeInOut(...)為呼叫tween.js中的方法,可根據實際需求修改Cubic或easeInOut的值。我把裡面所有的方法列表如下:
Linear | 線性勻速變化 |
||||
Quad | easeIn easeOut easeInOut |
二次方緩動 | Expo | easeIn easeOut easeInOut |
指數曲線緩動 |
Cubic | easeIn easeOut easeInOut |
三次方緩動 | Circ | easeIn easeOut easeInOut |
圓周曲線緩動 |
Quart | easeIn easeOut easeInOut |
四次方緩動 | Elastic | easeIn easeOut easeInOut |
彈性伸縮緩動 |
Quint | easeIn easeOut easeInOut |
五次方緩動 | Back | easeIn easeOut easeInOut |
返回緩動 |
Sine | easeIn easeOut easeInOut |
正弦曲線緩動 | Bounce | easeIn easeOut easeInOut |
跳動緩動 |