1. 程式人生 > >tween 緩動動畫

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  
跳動緩動