/*
* 动画类
* elem 动画dom对象
* prop 目标样式集合
* duration 总用时长
* callback 回调函数
* 原生JS
*/
var Animation = function(elem, prop, duration, callback){
if(!elem || elem.nodeType != 1) return;
this.elem = elem;
this.duration = duration;
this.callback = callback && typeof callback == 'function' ? callback : function(){};
this.interval = 13;
this.timer = null;
this.propStyle = {};
this.curStyle = {};
this.initStyle(elem, prop);
}
Animation.prototype = {
/*
* 格式化动画两极样式
* elem 动画dom对象
* prop 目标样式集合
* return this.curStyle:初始样式集合 this.propStyle:目标样式集合
* 支持opacity/width/height/left/top/marginLeft...等,单位px
*/
initStyle: function(elem, prop){
var isIE = /*@cc_on!@*/!1;
var currentStyle = elem.currentStyle || window.getComputedStyle(elem, null); //当前对象样式集合,包括css及style内样式
for(var o in prop){
var curVal = o=='opacity' && isIE ? currentStyle['filter'] : currentStyle[o];
if(o=='opacity' && isIE){
var match = curVal.match(/opacity=(\d+)/i);
curVal = match ? parseFloat(match[1]) / 100 : 1;
}else{
curVal = parseFloat(curVal);
}
if(typeof curVal == 'number'){
this.curStyle[o] = curVal;
//this.propStyle[o] = curVal + parseFloat(prop[o]);
this.propStyle[o] = parseFloat(prop[o]);
}
}
},
/*
* 执行函数
* 13ms为一帧 this.interval = 13
*/
run: function(){
var queue = parseInt(this.elem.getAttribute('animating')) || 0;
this.elem.setAttribute('animating', queue + 1);
this.startTime = this.now();
this.timer = setInterval(this.tick.bind(this), this.interval);
},
/*
* 结束动画并执行回调函数
*/
stop: function(){
clearInterval(this.timer);
this.timer = null;
var elem = this.elem;
var queue = parseInt(elem.getAttribute('animating')) || 0;
if(queue <= 1){
elem.removeAttribute('animating');
}else{
elem.setAttribute('animating', queue - 1);
}
this.callback.call(elem);
},
/*
* 返回对象当前动画数
*/
queue: function(){
return parseInt(this.elem.getAttribute('animating')) || 0;
},
/*
* 进度计算
* percent为当前进度,1时结束动画
*/
tick: function(){
var currentTime = this.now(),
remaining = Math.max( 0, this.startTime + this.duration - currentTime ), //剩余时间
temp = remaining / this.duration || 0, //剩余时间所占比例
percent = 1- temp; //当前进度
if(percent <= 1){
this.tweens(percent);
}else{
this.stop();
}
},
/*
* 动画
*/
tweens: function(percent){
var isIE = /*@cc_on!@*/!1;
var style = this.elem.style;
for(var o in this.propStyle){
var start = this.curStyle[o],
end = this.propStyle[o];
var now = start + ((end - start) * percent); //计算当前值
if(o == 'opacity'){
if(isIE){
style.filter = 'alpha(opacity='+ parseInt(now * 100) +')';
}else{
style.opacity = now;
}
}else{
style[o] = now + 'px';
}
}
if(percent == 1){
this.stop();
}
},
/*
* 返回当前时间戳
*/
now: function(){
return ( new Date() ).getTime();
}
}
var anim = new Animation(elem, {'height': 0}, 3000, function(){});
anim.run();