JS动画代码

/*
 * 动画类
 * 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();

 

posted on 2013-02-28 14:44  Lecaf  阅读(2153)  评论(1编辑  收藏  举报