大家都知道JQuerry有animate方法来给DOM元素进行运动,CSS3中也有transition、transform来进行运动。而使用原生的Javascript来控制元素运动,须要写非常多运动的细节以及兼容。
然而。当你的BOSS不让你使用庞大的JQ框架,并且你开发的产品也须要在一些不兼容CSS3的浏览器运行的时候。你是否认为每次都要开个定时器来琢磨运动该怎么进行,是件非常费力的事情呢?
那么福利来了,笔者近期总结了两个经常使用的运动框架,并将其写成组件,
仅仅要依照以下的方法调用。就可以方便使用。1.在你的页面中引入js
2.在你的js代码中创建Mover对象
3.開始使用mover!
使用方法说明:笔者写的组件包含了两种运动框架供使用。一种是基于速度的;一种是基于时间的。让我们来先看看基于速度的运动框架的使用方法startMoveBySpeed(obj, json, endFn);
參数obj : 传入要运动的对象
參数json : 以json的形式传入要运动的属性,包含left、top、width、height等以px为单位的属性和透明度opacity,他们的值是运动的终点
參数endFn(可选) : 结束运动后要运行的方法
让我们来看看第二种基于时间的运动框架
startMoveByTime(obj, json, options, endFn )
參数obj : 传入要运动的对象
參数json : 以json的形式传入要运动的属性。包含left、top、width、height等以px为单位的属性和透明度opacity。他们的值是运动的终点
參数options : 以json的形式传入传入运动的总时间和运动方式,如:
{ ‘times’ : 1000。//运动总时间为1s ‘fx’ : ‘linear’ // 运动形式为匀速 } 当options传入參数为空json{}时,就使用默认设置(运动时间500ms,运动形式为匀速)參数endFn(可选) : 结束运动后要运行的方法
//基于事件的运动框架使用方法window.onload=function(){ //得到你要运动的元素 var oDiv = document.getElementsByTagName('div')[0]; //使用运动框架 var mover = new Mover(); oDiv.onclick=function(){ mover.startMoveByTime( this, { 'left':500,'top':200}, { 'times':1000,'fx':'easeIn'}, function(){ mover.startMoveByTime(this,{ 'opacity':20},{}); }); //使oDiv的left变为500px,高度变为200px,结束上述运动后再使透明度变为20% }}
如今来说说两种方式的差别吧。使用第一种方式进行运动时。元素的各项须要改变的属性的运动速度同样,而因为每项属性起点到终点的距离不一样。所以各项属性到达运动终点的时间也不一样。
而第二种运动直接固定了运动总时间同样,所以全部传入參数的属性一起改变、一起终止。
以下是Mover.js组件的代码,笔者乃菜鸟一仅仅,欢迎指正。后面有时间也会将弹性运动、碰撞运动、重力运动一起写入框架
/* js原生运动组件*///Mover构造函数function Mover(){ this.setting = { 'times' : 500, 'fx' : 'linear' }}//获取当前样式Mover.prototype.getStyle = function(obj,attr){ return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj)[attr];}//获取当前时间Mover.prototype.now = function(){ return (new Date()).getTime();}//速度版运动框架Mover.prototype.startMoveBySpeed = function (obj,json,fnEnd){ clearInterval(obj.timer); _this = this; obj.timer = setInterval(function(){ obj.bStop = true; for(var attr in json) { var cur = 0; var speed = 0; if(attr === 'opacity') { cur = _this.getStyle(obj,attr); cur = Math.round( parseFloat(cur*100) ); } else { cur = parseInt(_this.getStyle(obj,attr)); } var speed = (json[attr]-cur)/8; speed = speed ? Math.ceil(speed):Math.floor(speed); if(cur !== json[attr]) { obj.bStop = false; } if(attr === 'opacity') { obj.style.opacity = (cur+speed)/100; obj.style.filter = 'Alpha(opacity:'+(cur+speed)+')'; } else { obj.style[attr] = (cur+speed)+'px'; } } if(obj.bStop) { clearInterval(obj.timer); fnEnd && fnEnd.call(obj); } },20);}//时间版运动框架Mover.prototype.startMoveByTime = function(obj,json,options,endFn){ //对于时间版框架来说。初始值b是固定的,所以写在定时器外面 var _this = this; //默认设置 extend(_this.setting,options); var iCur = {}; //获取当前值 for(attr in json) { iCur[attr] = 0; if(attr === 'opacity') { iCur[attr] = Math.round( parseFloat( _this.getStyle(obj,attr) )*100 ); }else{ iCur[attr] = parseInt( _this.getStyle(obj,attr) ); } }; var iStartTime = _this.now(); clearInterval(obj.timer); obj.timer = setInterval(function(){ var iCurTime = _this.now(); var t = _this.setting.times- Math.max(0,iStartTime-iCurTime+_this.setting.times); for(attr in json) { /* Tween[fx]函数4个參数 t:current time(当前时间) b:beginning value(初始值) c: change in value(变化量) d:duration(持续时间) return (目标点) */ var value = _this.Tween[_this.setting.fx]( t, //t 0~times iCur[attr], //b json[attr]-iCur[attr], //c _this.setting.times //d ); if(attr === 'opacity') { obj.style[attr] = parseFloat(value/100); obj.style.filter = 'alpha(opacity:'+value+')'; }else{ obj.style[attr] = value + 'px'; } } if( t === _this.setting.times ) { clearInterval(obj.timer); endFn && endFn.call(obj); } },13);}//覆盖默认设置function extend(child,father){ for(var attr in father) { child[attr] = father[attr]; }}//Tween运动算法Mover.prototype.Tween = { /* 4个參数 t:current time(当前时间) b:beginning value(初始值) c: change in value(变化量) d:duration(持续时间) return (目标点) */ linear: function (t, b, c, d){ //匀速 return c*t/d + b; }, easeIn: function(t, b, c, d){ //加速曲线 return c*(t/=d)*t + b; }, easeOut: function(t, b, c, d){ //减速曲线 return -c *(t/=d)*(t-2) + b; }, easeBoth: function(t, b, c, d){ //加速减速曲线 if ((t/=d/2) < 1) { return c/2*t*t + b; } return -c/2 * ((--t)*(t-2) - 1) + b; }, easeInStrong: function(t, b, c, d){ //加加速曲线 return c*(t/=d)*t*t*t + b; }, easeOutStrong: function(t, b, c, d){ //减减速曲线 return -c * ((t=t/d-1)*t*t*t - 1) + b; }, easeBothStrong: function(t, b, c, d){ //加加速减减速曲线 if ((t/=d/2) < 1) { return c/2*t*t*t*t + b; } return -c/2 * ((t-=2)*t*t*t - 2) + b; }}