Javascript动画系列之 —— lightbox实现(二)
2013-04-26 21:02 MoltBoy 阅读(1446) 评论(1) 编辑 收藏 举报上次帖子里详细描述了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")); //最后调用
代码还算清晰,主要的难点在于绑定的理解和兼容性的问题。