Javascript动画系列之 —— lightbox实现(二)

  上次帖子里详细描述了lightbox实现思路,本想将整个原生的lightbox源码放出来,但是觉得留点思考的余地更好。

  本文中就贴上淡入淡出和滑动的JS原生代码,通过测试,能兼容IE8、Firefox、Chrome。

function bind(fn, context){  //函数绑定,传递context上下文

    var args = Array.prototype.slice.call(arguments, 2);

    return function(){

        var innerArgs = Array.prototype.slice.call(arguments);

        var finalArgs = args.concat(innerArgs);  //柯里化参数

        return fn.apply(context, finalArgs);

    };

}

var addEvent = function(ele, event, fn){  //添加事件兼容

    ele.addEventListener ? ele.addEventListener(event, fn, false) :

    ele.attachEvent ? ele.attachEvent("on" + event, fn) : (ele["on" + event] = fn);

};

var animation = {

    config: {    //参数

        interval: 17,

        show: true,

        distance: 0,

        distanceW: 0                

    },

    calculate: function(strSpeed, height, width){    //几种模式不同的算法

        var speed = this.speedFn(strSpeed),

            i = this.config.interval;

        return typeof height === "undefined" && typeof width === "undefined" ?

        {

            frames: (speed - 0) / i,

            step: i / (speed - 0)

        } : {

            frames: (speed - 0) / i,

            step: i * height / (speed - 0),

            stepw: i * width / (speed - 0)

        }

    },

    trim: function(str){    //去掉两头空格,测试过速度相比其他trim方法快很多

        //return str.replace(/^\s*/, '').replace(/\s*$/, '');

        return str.replace(/^\s*|\s*$/, '');

    },

    speedFn: function(strSpeed){

        strSpeed = (this.trim(strSpeed)).toLowerCase();

        switch(strSpeed){

            case "fastest":

                return 400;

            case "faster":

                return 500;

            case "fast":

                return 600;

            case "normal":

                return 700;

            case "slow":

                return 800;

            case "slower":

                return 900;

            case "slowest":

                return 1000;

            case "debug":

                return 2000;

            default:

                return 500;

        }

    },

    fadeOut: function(ele, strSpeed){                    

        var count = 0, c = this.config, s = ele.style,

            m$ = this.calculate(strSpeed);

        ele.currentStyle ? (s.filter = "alpha(opacity=100)") : s.opacity = 1;



        try{

            setTimeout(function(){

                count++;

                if(count > m$.frames){                            

                    ele.currentStyle ? (s.filter = "alpha(opacity=0)") : s.opacity = 0;

                }else{

                    if(!ele.currentStyle){

                        s.opacity -= m$.step;

                    }else{

                        var f = parseFloat(ele.currentStyle.filter.match(/\d+/).toString());

                        f -= m$.step * 100;

                        s.filter = "alpha(opacity=" + f + ")";

                    }

                    setTimeout(arguments.callee, c.interval);

                }

            }, c.interval); 

        }catch(ex){

            console.log("fadeOut error, " + ex.message);

        }

        c.show = false;

    },

    fadeIn: function(ele, strSpeed){

        var count = 0, c = this.config, s = ele.style,

            m$ = this.calculate(strSpeed);

        ele.currentStyle ? (s.filter = "alpha(opacity=0)") : s.opacity = 0;



        try{

            setTimeout(function(){

                count++;

                if(count > m$.frames){                            

                    ele.currentStyle ? (s.filter = "alpha(opacity=100)") : s.opacity = 1;

                }else{

                    if(ele.currentStyle){

                        var f = parseFloat(ele.currentStyle.filter.match(/\d+/).toString());

                        f += m$.step * 100;

                        s.filter = "alpha(opacity=" + f + ")";

                    }else{

                        s.opacity = parseFloat(s.opacity) + m$.step;

                    }

                    setTimeout(arguments.callee, c.interval);

                } 

            }, c.interval); 

        }catch(ex){

            console.log("fadeIn error, " + ex.message);

        }

        c.show = true;

    },

    fadeToggle: function(ele, strSpeed){    //淡入淡出切换

        var self = this;

        setTimeout(function(){                        

            self.config.show ? self.fadeOut(ele, strSpeed) : self.fadeIn(ele, strSpeed);

        }, 0);

    },

    slideOut: function(ele, strSpeed){

        var count = 0, u = "px", s = ele.style,

            c = this.config, cs = window.getComputedStyle ? window.getComputedStyle(ele) : ele.currentStyle,

            h = s.height = c.distance = parseFloat(cs["height"]),

            w = s.width = c.distanceW = parseFloat(cs["width"]);



        try{

            var    m$ = this.calculate(strSpeed, h, w);

            setTimeout(function(){

                count++;

                if(count > m$.frames || parseFloat(s.width) < m$.stepw || parseFloat(s.height) < m$.step){

                    s.height = 0;

                    s.width = 0;

                }else{

                    s.height = (parseFloat(s.height) - m$.step) + u;

                    s.width = (parseFloat(s.width) - m$.stepw) + u;

                    setTimeout(arguments.callee, c.interval);

                }

            }, c.interval); 

        }catch(ex)

        {

            console.log("slideOut error, " + ex.message);

        }

        c.show = false;

    },

    slideIn: function(ele, strSpeed){

        var count = 0, u = "px", s = ele.style,

            c = this.config, cs = window.getComputedStyle ? window.getComputedStyle(ele) : ele.currentStyle,

            h = c.distance,

            w = c.distanceW;

        try{

            var    m$ = this.calculate(strSpeed, h, w);

            setTimeout(function(){

                count++;

                if(count > m$.frames || parseFloat(s.width) > c.distanceW || parseFloat(s.height) > c.distance){                            

                    s.height = c.distance + u;

                    s.width = c.distanceW + u;

                }else{

                    s.height = (parseFloat(s.height) + m$.step) + u;

                    s.width = (parseFloat(s.width) + m$.stepw) + u;

                    setTimeout(arguments.callee, c.interval);

                }

            }, c.interval);

        }catch(ex){

            console.log("slideOut error, " + ex.message);

        }

        c.show = true; 

    },

    slideToggle: function(ele, strSpeed){

        this.config.show ? this.slideOut(ele, strSpeed) : this.slideIn(ele, strSpeed);

    }

};



addEvent(btn, "click", bind(animation.fadeToggle, animation, element, "normal"));  //最后调用

  代码还算清晰,主要的难点在于绑定的理解和兼容性的问题。

你可能感兴趣的:(JavaScript)