|
最近,同事在做一个项目的时候,有个需求,需要一款动画库来支持
要求如下: 可以开始、暂停(线性、非线性tween都支持)、继续、结束 支持多个样式并行 最好不依赖于某个框架下运行 文件尺寸越小越好 他找了一下现有的一些插件或者库,鲜有能满足或者比较均衡的,我在这个要求下,写了一个比较简陋的动画组件,基本满足了这个需求。先上代码 在线演示:http://demo.jb51.net/js/2012/animate/ 打包下载:animate_jquery.rar html部分: 复制代码 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>animate</title> <script type="text/javascript" src="tangram-1.5.0.core.js"></script> <script type="text/javascript" src="jquery.min.js"></script> <style> html,body,ul,li{padding:0;margin:0;} #anim{width:50px;height:50px;background:red;position:absolute; top:30px;left:0;} </style> </head> <body> <div> <input type="button" value="start" onclick="an.start()" /> <input type="button" value="pause" onclick="an.pause()" /> <input type="button" value="resume" onclick="an.resume()" /> <input type="button" value="stop" onclick="an.stop()" /> <a target="_self" id="demolink" href="animate.html?demo=1" />auto start,pasue,then resume</a> </div> <div id="anim"></div> </body></html> animate部分: 复制代码 代码如下: function animate(options){ this.from = options.from;//如果没有from,就计算出from this.to = options.to || {}; this.onStart = options.onStart || empty;//以下是一些回调函数,就不采用事件机制了 this.onStop = options.onStop || empty; this.onAnimate = options.onAnimate || empty; this.onContinue = options.onContinue || empty; this.onPause = options.onPause || empty; var element = options.element; var duration = options.duration || 300;//变化的总时长,单位是ms var pending = false;//是不是已经暂停了,如果还木有开始的话,该值也是true var timer = null; var mixin = options.mix; var defaultState = this.from || getState(element, this.to);//原始的数据 var thiz = this; //获取最初始的样式 function getState(ele, targetStyles){ var obj = {}; var i = 0; for (var p in targetStyles) { i++; obj[p] = parseFloat(mixin.getStyle(ele, p)); } if(i == 0){ return null; } return obj; } function empty(){} function animate(from, to, elapse){ var startTime = (new Date).getTime() + (elapse ? - elapse : 0);//如果有第三个参数,证明是从一个暂停开始的,那么就设置startTime为当前时间减去暂定时已经逝去的时间,如果只有两个参数,那么逝去时间就是0 timer = setInterval(function(){ var endTime = (new Date).getTime(); if(endTime - startTime < duration){ thiz.onAnimate(); currentElapse = endTime - startTime; for(var p in from){ if(from.hasOwnProperty(p)){ var currentPropertyStyle = mixin.compute(currentElapse, from[p], to[p]-from[p], duration); mixin.setStyle(element, p, currentPropertyStyle); } } } else{ thiz.stop(thiz.to); } }, 16); } this.start = function(){ if(pending){ this.resume(); } else{ this.onStart(); animate(defaultState, this.to); } } this.stop = function(){ clearInterval(timer); var styles = this.to; for(var p in styles){ if(styles.hasOwnProperty(p)){ mixin.setStyle(element, p, styles[p]); } } this.onStop(); } this.pause = function(){ clearInterval(timer); pending = true; this.onPause(); } this.resume = function(){ pending = false; this.onContinue(); animate(defaultState, this.to, currentElapse); } } 使用部分: 复制代码 代码如下: var mixinT = { getStyle:baidu.dom.getStyle, setStyle:baidu.dom.setStyle, compute:function(t, b, c, d){ //return t*c/d + b; if (t==0) return b; if (t==d) return b+c; if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; } }; var mixinJQ = { getStyle:function(ele, styleName){ return $(ele).css(styleName); }, setStyle:function(ele, styleName, styleValue){ $(ele).css(styleName, styleValue); }, compute:function(t, b, c, d){ return b+ t*c/d; } }; var an = new animate({ element:document.getElementById('anim'), //from:{'width':100, 'height':100, left:0, top:30}, to:{left:500}, mix:mixinT, duration:2000 }); if(/demo=1/.test(location.search)){ var demolink = baidu.g('demolink'); demolink.href= 'animate.html'; demolink.innerHTML = 'back'; an.start(); setTimeout(function(){ an.pause(); resume(); }, 1200); function resume(){ setTimeout(function(){an.resume()}, 1000); } } 上面是一个完整demo的代码。做几点说明: 代码尺寸足够小了,一共才100行,gzip后连1k都不到。 满足了可以start、pause、resume、stop的需求,赠送了几个回调函数:D。 可以支持多个样式一起变化。 采用了一个mixin变量,传进来三个函数需要在执行动画时的操作,getStyle、setStyle、compute,我感觉这三个确实和用户的选择有关系,前两个可能和框架有关,第三个和用户采用的变化计算方式有关,之所以传进去四个参数,主要是和主流的tween类能适应起来,可以参考http://www.robertpenner.com/easing/和http://www.actionscript.org/resources/articles/170/1/Flash-MX-2004-Undocumented-TweenEasing-Classes-Documented/Page1.html。我给的例子用了tangram和jquery俩类库,分别对应了两个mixin对象,做一下简单的适配,就能用了。 一些“私有”变量和函数放闭包里了,这样初始化一个animate的时候,对象是干净的,但是缺点就是占用内存多了,每个实例都维护自己的方法。 使用的时候,可以不提供options.from,函数会根据额options.to来计算from中对应样式的值,这很大程度上依赖于mixin提供的方法够不够强大,所以这一块还是有bug 的,不过,80%的功能够用了。麻雀虽小,五脏俱全了。 |
|