在讲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 |
跳动缓动 |
请查看本人写的Demo,里面包含了所有效果:www.chengguanhui.com/demos/tween/index.html