动画原理
所谓的动画,就是通过一些列的运动形成的动的画面。在网页中,我们可以通过不断的改变元素的css值,来达到动的效果。
用到的公式
总距离S = 总时间T * 速度V 即: V = S/T 当前距离s = S/T * 已耗时t 即: s = S * (t/T) 即:当前距离 = 总距离 * (已耗时/总时间) 即:动画元素开始值 + (动画元素结束值 - 动画元素开始值) * (当前时间-开始时间) / (动画需要时间) + 值的格式
有了上面这些公式,我们就能利用javascript的setInterval或者setTimeout来做一个简单的动画了。 然而想要做一个动画库,就不得不考虑另外一些因素了。 比如同一个元素的动画,必须要有顺序的执行。不同元素的动画可以同步运行。
如此一来,就必须得用另外一个对象来管理这些动画了。我开始的想法是讲每个元素都放在一个数组里,用几个setInterval来循环取出数组中的动画函数依次执行。
animate1 = [{elem,fn},{elem,fn}]; animate2 = [{elem,fn},{elem,fn}];
这样就能达到,相同的元素动画,是有顺序的执行,而不同的则可以同时运行了。然后这样却存在一个问题,那就是如果超过10个元素的动画。程序就要开十个setInterval。
为了避免这样的情况发生,就在上面的基础上做了一些改进。使得,不论多少个动画。都使用一个setInterval来完成。修改后结构如下。
[ [elem,[fn,fn,fn,fn]], [elem,[fn,fn,fn,fn]], [elem,[fn,fn,fn,fn]] ]
这样一来,就可以用一个setInterval来完成所有动画了。 所需要做就是,循环取出elem,并执行elem后面一个元素的头一个fn,fn执行完毕后删除fn。调用下一个fn,如果fn全部为空则从大的数组中删除elem,如果elem为空时,则清楚setInterval。这样一来,逻辑上便可以走得通了。
然而动画最关键的因素还有一个,那就是缓动。 如果没有缓动,那么动画效果看起来就非常的死板。千篇一律。目前做js动画用到的缓动算法是很多的,大致分为两类。 一种是flash类,一种是prototype类。
flash的需要四个参数。分别是, 1.时间初始话的时间t 2.动画的初始值b 3.动画的结束值c 4.动画持续的时间d 下面是一个flash 类的匀速运动算法 Linear: function(t,b,c,d){ return c*t/d + b; } 另一种则是prototype,这一类的参数只需要一个,那就是当前时间t与持续时间d的比值 (t/d) 我采用了第二种,因为它的参数方便。也更加适合上面的动画公式,下面是一个prototype类的匀速运动算法 linear : function(t){ return t;}. 加入缓动后上面的公式变为 动画元素开始值 + (动画元素结束值 - 动画元素开始值) * 缓动函数((当前时间-开始时间) / (动画需要时间)) + 值的格式。 至此便是整个动画类设计便结束了。其中参考了一些其它人的博客,在此表示感谢! 最后,还是贴一下详细代码吧。
/** * create time 2012/08/29 * @author lynx cat. * @version 0.77beta. */
(function(win,doc){ var win = win || window; var doc = doc || win.document, pow = Math.pow, sin = Math.sin, PI = Math.PI, BACK_CONST = 1.70158; var Easing = { // 匀速运动 linear : function(t){ return t; }, easeIn : function (t) { return t * t; }, easeOut : function (t) { return ( 2 - t) * t; }, easeBoth : function (t) { return (t *= 2) < 1 ? .5 * t * t : .5 * (1 - (--t) * (t - 2)); }, easeInStrong : function (t) { return t * t * t * t; }, easeOutStrong : function (t) { return 1 - (--t) * t * t * t; }, easeBothStrong: function (t) { return (t *= 2) < 1 ? .5 * t * t * t * t : .5 * (2 - (t -= 2) * t * t * t); }, easeOutQuart : function(t){ return -(pow((t-1), 4) -1) }, easeInOutExpo : function(t){ if(t===0) return 0; if(t===1) return 1; if((t/=0.5) < 1) return 0.5 * pow(2,10 * (t-1)); return 0.5 * (-pow(2, -10 * --t) + 2); }, easeOutExpo : function(t){ return (t===1) ? 1 : -pow(2, -10 * t) + 1; }, swingFrom : function(t) { return t*t*((BACK_CONST+1)*t - BACK_CONST); }, swingTo: function(t) { return (t-=1)*t*((BACK_CONST+1)*t + BACK_CONST) + 1; }, sinusoidal : function(t) { return (-Math.cos(t*PI)/2) + 0.5; }, flicker : function(t) { var t = t + (Math.random()-0.5)/5; return this.sinusoidal(t < 0 ? 0 : t > 1 ? 1 : t); }, backIn : function (t) { if (t === 1) t -= .001; return t * t * ((BACK_CONST + 1) * t - BACK_CONST); }, backOut : function (t) { return (t -= 1) * t * ((BACK_CONST + 1) * t + BACK_CONST) + 1; }, {JyNxnh8"#&WGW&V'##WgV#"2F3#"fgV#"BFFRrF2'EF#FFRrfF2'EFF2FGW&F#BfB#"f"2&vWB#GV2W&6Uwfv&W"r#"f'6TfBF2W&6UwfF2&vWEwfF2W&6UwfF2FV6B2FGW&FfVBr#W#""'6TF2W&6Uwfw"uF2&vWEwfw"uF2W&6Uwfw"uF2FV6B2FGW&F#"r'6TF2W&6UwfvruF2&vWEwfvruF2W&6UwfvruF2FV6B2FGW&F#""'6TF2W&6Uwfv"uF2&vWEwfv"uF2W&6Uwfv"uF2FV6B2FGW&F#"fw&v"r"rrr"rs##6WE7GF2VF2W&6UwVu##W#"f"2&vWB#GV2&vWEwfv&W"r#"fF2&vWEwf#W#"fw&v"rF2&vWEwfw"urF2&vWEwfvrurF2&vWEwfv"urs##6WE7GVF2W&6UwVu##"6BFV#&W2gB#2F6&6#6#6WE7GVvfrr2W&fr#&VfTFFV####GW&V#2'EF#"6R#2&vWB2#"f"F2#"fBE7G2V#W&6UB'6U7Gf##2W&6R6S#2'EFFFRr#2W&frBE7GVvfrr#6WE7GVvfrrFFV##2#####ZIn:h8"##R#'V7F8g##XyKikk9R#&&'#&GW&F'#&V6#&6&6#&WGW&7G##FRgV&GW&FV66&6#&wV2ffGV6vgVi[i{nX yJh~zKKXi2#&6V6#6Vf##"&B'6U&&#"BD2VGW&F66&6#"6g6F2V&#GW&3###XXyKikk9R#KyJikk9R6F2wVBr##gV#&VfTFFF2V###Fg6Fg#F2V#Fc'#~iK>zNhFgtBrFRv&vVgBs#&6w&sr6fcwcV6TV##W'yNKyJikk9^[zIh.izKXCj8.KzKKXX KXKX{[nKNhX[XKKXi{n8.zKKXKY>8"##6FgtBrFRv&vVgBs#&6w&sr6fcwcV'B~kI.Z>X{[ |