动画组件animator

废话不多说,直接贴代码:

(function(ns) {
    var Tween = {
        Linear: function(t, b, c, d) {
            return c * t / d + b;
        },
        Quad: {
            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;
            },
            easeInOut: function(t, b, c, d) {
                if ((t /= d / 2) < 1) return c / 2 * t * t + b;
                return - c / 2 * ((--t) * (t - 2) - 1) + b;
            }
        },
        Cubic: {
            easeIn: function(t, b, c, d) {
                return c * (t /= d) * t * t + b;
            },
            easeOut: function(t, b, c, d) {
                return c * ((t = t / d - 1) * t * t + 1) + b;
            },
            easeInOut: function(t, b, c, d) {
                if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
                return c / 2 * ((t -= 2) * t * t + 2) + b;
            }
        },
        Quart: {
            easeIn: function(t, b, c, d) {
                return c * (t /= d) * t * t * t + b;
            },
            easeOut: function(t, b, c, d) {
                return - c * ((t = t / d - 1) * t * t * t - 1) + b;
            },
            easeInOut: 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;
            }
        },
        Quint: {
            easeIn: function(t, b, c, d) {
                return c * (t /= d) * t * t * t * t + b;
            },
            easeOut: function(t, b, c, d) {
                return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
            },
            easeInOut: function(t, b, c, d) {
                if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
                return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
            }
        },
        Sine: {
            easeIn: function(t, b, c, d) {
                return - c * Math.cos(t / d * (Math.PI / 2)) + c + b;
            },
            easeOut: function(t, b, c, d) {
                return c * Math.sin(t / d * (Math.PI / 2)) + b;
            },
            easeInOut: function(t, b, c, d) {
                return - c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
            }
        },
        Expo: {
            easeIn: function(t, b, c, d) {
                return (t == 0) ? b: c * Math.pow(2, 10 * (t / d - 1)) + b;
            },
            easeOut: function(t, b, c, d) {
                return (t == d) ? b + c: c * ( - Math.pow(2, - 10 * t / d) + 1) + b;
            },
            easeInOut: function(t, b, c, d) {
                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;
            }
        },
        Circ: {
            easeIn: function(t, b, c, d) {
                return - c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
            },
            easeOut: function(t, b, c, d) {
                return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
            },
            easeInOut: function(t, b, c, d) {
                if ((t /= d / 2) < 1) return - c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
                return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
            }
        },
        Elastic: {
            easeIn: function(t, b, c, d, a, p) {
                if (t == 0) return b;
                if ((t /= d) == 1) return b + c;
                if (!p) p = d * .3;
                if (!a || a < Math.abs(c)) {
                    a = c;
                    var s = p / 4;
                }
                else var s = p / (2 * Math.PI) * Math.asin(c / a);
                return - (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
            },
            easeOut: function(t, b, c, d, a, p) {
                if (t == 0) return b;
                if ((t /= d) == 1) return b + c;
                if (!p) p = d * .3;
                if (!a || a < Math.abs(c)) {
                    a = c;
                    var s = p / 4;
                }
                else var s = p / (2 * Math.PI) * Math.asin(c / a);
                return (a * Math.pow(2, - 10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
            },
            easeInOut: function(t, b, c, d, a, p) {
                if (t == 0) return b;
                if ((t /= d / 2) == 2) return b + c;
                if (!p) p = d * (.3 * 1.5);
                if (!a || a < Math.abs(c)) {
                    a = c;
                    var s = p / 4;
                }
                else var s = p / (2 * Math.PI) * Math.asin(c / a);
                if (t < 1) return - .5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
                return a * Math.pow(2, - 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
            }
        },
        Back: {
            easeIn: function(t, b, c, d, s) {
                if (s == undefined) s = 1.70158;
                return c * (t /= d) * t * ((s + 1) * t - s) + b;
            },
            easeOut: function(t, b, c, d, s) {
                if (s == undefined) s = 1.70158;
                return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
            },
            easeInOut: function(t, b, c, d, s) {
                if (s == undefined) s = 1.70158;
                if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
                return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
            }
        },
        Bounce: {
            easeIn: function(t, b, c, d) {
                return c - Tween.Bounce.easeOut(d - t, 0, c, d) + b;
            },
            easeOut: function(t, b, c, d) {
                if ((t /= d) < (1 / 2.75)) {
                    return c * (7.5625 * t * t) + b;
                } else if (t < (2 / 2.75)) {
                    return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
                } else if (t < (2.5 / 2.75)) {
                    return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
                } else {
                    return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
                }
            },
            easeInOut: function(t, b, c, d) {
                if (t < d / 2) return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;
                else return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
            }
        }
    }
    function Animator(options) {
        var __self__ = this,
        config = {
            obj: null,
            css: {},
            time_start: 0,
            time_end: 100,
            callback: null,
            step: null
        }
        for (var a in options) {
            config[a] = options[a];
        }
        this.config = config;
        this.init();
    }

    Animator.prototype = {
        init: function() {
            var __self__ = this;
            for (var a in Tween) {
                if (Tween[a].constructor === Object) {
                    __self__[a] = {};
                    for (var b in Tween[a]) {
                        __self__[a][b] = (function(easing) {
                            return function() {
                                return __self__.buffer(easing);
                            }
                        })(Tween[a][b])
                    }
                } else {
                    __self__[a] = (function(easing) {
                        return function() {
                            return __self__.buffer(easing);
                        }
                    })(Tween[a])
                }
            }
            return this;
        },
        animation: function(obj, attr, time_start, time_end, begin_state, end_state, easing, callback, step) {    
            var __self__ = this,
            obj = obj,
            attr = attr,
            t = time_start,
            b = begin_state,
            c = end_state - begin_state,
            d = time_end;
            easing = easing;
            __self__.Timer = null;
            console.log(obj.anamation_fixed);
            if(obj.anamation_fixed){
                return this;
            }else{
                obj.anamation_fixed = true;
            }
            (function() {
                __self__.Timer && clearTimeout(__self__.Timer);
                var fn = arguments.callee;
                if (attr === "opacity") {
                    obj.style[attr] = easing(t, b, c, d);
                } else {
                    obj.style[attr] = Math.ceil(easing(t, b, c, d)) + "px";
                }
                if (t < d) {
                    t++;
                    __self__.Timer = setTimeout(fn, 16);
                } else {
                    obj.anamation_fixed = false;
                    callback && callback();
                }
            })();
            return this;
        },
        buffer: function(easing) {
            var __self__ = this,
            css = this.config.css,
            config = this.config;
            for (var a in css) {
                var curSty;
                if (document.defaultView) {
                    curSty = (function() {
                        return document.defaultView.getComputedStyle(config.obj, false)
                    })();
                } else {
                    curSty = config.obj.currentStyle;
                }
                begin_state = parseInt(curSty[a]);
                __self__.animation(config.obj, a, config.time_start, config.time_end, begin_state, config.css[a], easing, config.callback, config.step);
            }
            return this;
        }
    }
    ns.Animator = Animator;
    ns.animator = function(obj, attr, end, callback, time) {
        var obj = (typeof obj === "string") ? document.getElementById(obj) : obj,
        option = {
            obj: obj,
            css: {},
            callback: callback
        };
        option.css[attr] = end;
        callback && (option.callback = callback);
        time && (option.time_end = time);
        return new Animator(option);
    }
    ns.animator.extend = function(obj) {
        for (var a in obj) {
            this[a] = obj[a];
        }
    }
    var $ = function(id) {
        return (typeof id === "object") ? id: document.getElementById(id);
    }
    ns.animator.extend({
        fadeIn: function(obj, fn) {
            var obj = $(obj);
            var animate = animator(obj, "opacity", 1, fn, 10);
            animate.Linear();
        },
        fadeOut: function(obj, fn) {
            var obj = $(obj);
            var animate = animator(obj, "opacity", 0, fn, 10);
            animate.Linear();
        },
        slideUp: function(obj, fn) {
            var obj = $(obj);
            var styHeight = obj.style.height;
            var overflowY = obj.style.overflowY;
            var height = parseInt(styHeight);
            obj.style.overflowY = "hidden";
            obj.style.display = "block";
            if (!height) {
                if (document.defaultView) {
                    curSty = (function() {
                        return document.defaultView.getComputedStyle(obj, false)
                    })();
                } else {
                    curSty = obj.currentStyle;
                }
                height = parseInt(curSty.height);
            }
            obj.style.height = height+"px";
            var animate = animator(obj, "height", 0, function() {
                obj.style.display = "none";

                if (styHeight) {
                    obj.style.height = styHeight + "px";
                } else {
                    obj.style.height = "";
                }

                if (overflowY) {
                    obj.style.overflowY = overflowY;
                } else {
                    obj.style.overflowY = "";
                }

                fn && fn();
            },
            5);
            animate.Circ.easeOut();
        },
        slideDown: function(obj, fn) {
            var obj = $(obj);
            var curSty;
            var styHeight = obj.style.height;
            var overflowY = obj.style.overflowY;
            var height = parseInt(styHeight);
            obj.style.overflowY = "hidden";
            obj.style.display = "block";
            if (!height) {
                if (document.defaultView) {
                    curSty = (function() {
                        return document.defaultView.getComputedStyle(obj, false);
                    })();
                } else {
                    curSty = obj.currentStyle;
                }
                height = parseInt(curSty.height);
            }
            obj.style.height = "0px";
            var animate = animator(obj, "height", height, function() {
                
                if(styHeight){
                    obj.style.height = styHeight+"px";
                }else{
                    obj.style.height = "";
                }
                
                if (overflowY) {
                    obj.style.overflowY = overflowY;
                } else {
                    obj.style.overflowY = "";
                }
                fn && fn();
            },
            10);
            animate.Circ.easeOut();
        }
    });
})(this);

兼容性没时间测试,项目中只用到了slideUp,slideDown需求是兼容ie9,firefox,chrome,

就当个简单的学习对象吧,做个记录。

 

后续修正:

由于ie下,currentStyle的太2,居然可以获取到width:"auto"这样的东西,实在要命,老子没脾气,

不够过ie9以上都可以使用document.defaultView,

so,计划以后再需要用到animator的时候,采用getBoundingClientRect方法,获得的上下左右,再减去margin,padding,border等,可以影响到盒子模型的属性。

做个记录,免得日后忘记,时间不允许,就不修改animator了。

 

sorry,sorry,强烈sorry,我可以用offsetWidth,offsetHeight,然后根据盒模型再去计算,突然脑子热了,翻了个getBoundingClientRect.

posted @ 2012-05-09 08:08  潴哥  阅读(542)  评论(0)    收藏  举报