Open lynxerzhang opened 6 years ago
var root = document.getElementById("playground"); var e = createChild(); root.appendChild(e); function createChild() { var e = document.createElement("div"); e.style.position = "absolute"; e.style.width = "50px"; e.style.height = "10px"; e.style.top = "10px"; e.style.left = "500px"; e.style.background = "blue"; return e; } setTimeout(function(){ var d = new DomAnimationX(e, {"x":-550 * .5, "duration":5000 * .5}); d.add("complete", function(){ setTimeout(function(){ d = new DomAnimationX(e, {"x":-550, "duration":5000 * .5}); f.add(d); }, 3000); }) var f = new TickDomManager(); f.add(d); f.start(); }, 0); //使用transform对dom进行位移,同时又使用transition监听dom上的transfrom位移来达到线性动画的目的。 var TickDomManager = (function(){ function TickDomManager(){ this.domAnList = []; var self = this; this.tick = new Animation(function(t){ self.tickCallback(t); }); } var p = TickDomManager.prototype; p.start = function() { this.tick.start(); var len = this.domAnList.length; var d; for(var i = 0; i < len; i ++){ d = this.domAnList[i]; if(d){ d.start(); } } } p.stop = function() { this.tick.stop(); var len = this.domAnList.length; var d; for(var i = 0; i < len; i ++){ d = this.domAnList[i]; if(d){ d.stop(); } } } p.tickCallback = function(time) { var len = this.domAnList.length; var d; for(var i = 0; i < len; i ++){ d = this.domAnList[i]; if(d){ d.tick(time); } } } p.add = function(domAn) { domAn.start(); var self = this; domAn.add("complete", function(){ self.remove(this); this.destroy(); }.bind(domAn)); //bind 方法执行上下文环境 this.domAnList.push(domAn); } p.remove = function(domAn) { var len = this.domAnList.length; var d; for(var i = len - 1; i >= 0; i --){ d = this.domAnList[i]; if(d && d == domAn){ break; } } if(i >= 0 && i < len){ this.domAnList.splice(i, 1); } } return TickDomManager; })(); var DomAnimationX = (function(){ function DomAnimationX(dom, data) { this.dom = dom; this.data = data; this.duration = data.duration; this.lifeDuration = this.duration; this.delay = data.delay || 0; this.watch = createEventDispatch(); } var p = DomAnimationX.prototype; p.destroy = function() { this.dom = null; this.data = null; this.watch = null; } p.start = function() { Animation.setTransition(this.dom, "transform " + this.lifeDuration + "ms linear " + this.delay + "ms"); Animation.setTransform(this.dom, "translateX(" + this.data.x + "px)"); this.dispatch("start"); } p.stop = function() { var d = this.data.x * ((this.duration - this.lifeDuration) / this.duration); Animation.setTransition(this.dom, ""); Animation.setTransform(this.dom, "translateX(" + d + "px)"); this.dispatch("stop"); } p.tick = function(time) { if(this.lifeDuration <= 0){ this.lifeDuration = 0; this.dispatch("complete"); return; } this.lifeDuration -= time; } p.add = function(e, h) { this.watch.add(e, h); } p.remove = function(e, h) { this.watch.remove(e, h); } p.dispatch = function(e) { this.watch.dispatch(e); } return DomAnimationX; })(); var createEventDispatch = (function(){ return function() { var watch = {}; watch.listener = {}; watch.add = function(e, h){ var s = this.listener[e]; if(!s){ this.listener[e] = [h]; } else{ if(s.indexOf(h) < 0){ s.push(h); } } } watch.remove = function(e, h) { var s = this.listener[e]; if(s){ var len = s.length; if(arguments.length == 1){ s.length = 0; s = null; this.listener[e] = s; }else{ for(var i = len - 1; i >= 0; i--){ if(s[i] == h){ break; } } if(i >= 0 && i < len){ s.splice(i, 1); } } } } watch.dispatch = function(e){ var s = this.listener[e]; if(s){ var len = s.length; var d; for(var i = len - 1; i >= 0; i --){ d = s[i]; d(e); } } } return watch; } })(); var Animation = (function(){ function Animation(callback){ this.callback = callback; this.running = false; this.shouldKill = false; this.last = 0; this.now = 0; } Animation.setTransition = function(dom, trans) { dom.style.transition = trans; dom.style.webkitTransition = trans; dom.style.mozTransition = trans; dom.style.msTransition = trans; dom.style.oTransition= trans; } Animation.setTransform = function(dom, trans){ dom.style.transform = trans; dom.style.webkitTransform = trans; dom.style.mozTransform = trans; dom.style.msTransform = trans; dom.style.oTransform = trans; } Animation.request = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ callback(); }; })(); var p = Animation.prototype; p.start = function() { this.last = new Date().getTime(); this.shouldKill = false; if (!this.running) { this.running = true; this.render(); } }; p.stop = function() { this.shouldKill = true; this.last = 0; this.now = 0; }; p.toggle = function() { if (this.running) { this.stop(); } else { this.start(); } }; p.render = function() { if(this.shouldKill) { this.shouldKill = false; this.running = false; } if (this.running) { this.now = new Date().getTime(); if (this.callback) { this.callback(this.now - this.last); } this.last = this.now; var self = this; //Animation.request的调用需要如此,不然会报错,原因是该方法上下文执行环境被修改 Animation.request.call(null, function(){ self.render(); }); } }; p.dispose = function() { this.stop(); this.callback = null; this.running = false; this.shouldKill = false; }; return Animation; })();