diff options
Diffstat (limited to 'js/dojo/dojox/css3/transition.js')
| -rw-r--r-- | js/dojo/dojox/css3/transition.js | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/js/dojo/dojox/css3/transition.js b/js/dojo/dojox/css3/transition.js new file mode 100644 index 0000000..0a2f4b3 --- /dev/null +++ b/js/dojo/dojox/css3/transition.js @@ -0,0 +1,345 @@ +//>>built +define("dojox/css3/transition", ["dojo/_base/kernel", + "dojo/_base/lang", + "dojo/_base/declare", + "dojo/_base/array", + "dojo/_base/Deferred", + "dojo/DeferredList", + "dojo/on", + "dojo/_base/sniff"], + function(dojo, lang, declare, array, deferred, deferredList, on, has){ + //TODO create cross platform animation/transition effects + var transitionEndEventName = "transitionend"; + var transitionPrefix = "t"; //by default use "t" prefix and "ransition" to make word "transition" + var translateMethodStart = "translate3d(";//Android 2.x does not support translateX in CSS Transition, we need to use translate3d in webkit browsers + var translateMethodEnd = ",0,0)"; + if(has("webkit")){ + transitionPrefix = "WebkitT"; + transitionEndEventName = "webkitTransitionEnd"; + }else if(has("mozilla")){ + transitionPrefix = "MozT"; + translateMethodStart = "translateX("; + translateMethodEnd = ")"; + } + + //TODO find a way to lock the animation and prevent animation conflict + declare("dojox.css3.transition", null, { + + + constructor: function(args){ + //default config should be in animation object itself instead of its prototype + //otherwise, it might be easy for making mistake of modifying prototype + var defaultConfig = { + startState: {}, + endState: {}, + node: null, + duration: 250, + "in": true, + direction: 1, + autoClear: true + }; + + lang.mixin(this, defaultConfig); + lang.mixin(this, args); + + //create the deferred object which will resolve after the animation is finished. + //We can rely on "onAfterEnd" function to notify the end of a single animation, + //but using a deferred object is easier to wait for multiple animations end. + if(!this.deferred){ + this.deferred = new deferred(); + } + }, + + play: function(){ + //play the animation using CSS3 Transition + dojox.css3.transition.groupedPlay([this]); + }, + + //method to apply the state of the transition + _applyState: function(state){ + var style = this.node.style; + for(var property in state){ + if(state.hasOwnProperty(property)){ + style[property] = state[property]; + } + } + }, + + //method to initialize state for transition + initState: function(){ + + //apply the immediate style change for initial state. + this.node.style[transitionPrefix + "ransitionProperty"] = "none"; + this.node.style[transitionPrefix + "ransitionDuration"] = "0ms"; + this._applyState(this.startState); + + }, + + _beforeStart: function(){ + if (this.node.style.display === "none"){ + this.node.style.display = ""; + } + this.beforeStart(); + }, + + _beforeClear: function(){ + this.node.style[transitionPrefix + "ransitionProperty"] = null; + this.node.style[transitionPrefix + "ransitionDuration"] = null; + if(this["in"] !== true){ + this.node.style.display = "none"; + } + this.beforeClear(); + }, + + _onAfterEnd: function(){ + this.deferred.resolve(this.node); + if(this.node.id && dojox.css3.transition.playing[this.node.id]===this.deferred){ + delete dojox.css3.transition.playing[this.node.id]; + } + this.onAfterEnd(); + }, + + beforeStart: function(){ + + }, + + beforeClear: function(){ + + }, + + onAfterEnd: function(){ + + }, + + //method to start the transition + start: function(){ + this._beforeStart(); + + var self = this; + //change the transition duration + self.node.style[transitionPrefix + "ransitionProperty"] = "all"; + self.node.style[transitionPrefix + "ransitionDuration"] = self.duration + "ms"; + + //connect to clear the transition state after the transition end. + //Since the transition is conducted asynchronously, we need to + //connect to transition end event to clear the state + on.once(self.node, transitionEndEventName, function(){ + self.clear(); + }); + + this._applyState(this.endState); + }, + + //method to clear state after transition + clear: function(){ + this._beforeClear(); + this._removeState(this.endState); + console.log(this.node.id + " clear."); + this._onAfterEnd(); + }, + + //create removeState method + _removeState: function(state){ + var style = this.node.style; + for(var property in state){ + if(state.hasOwnProperty(property)){ + style[property] = null; + } + } + } + + }); + + //TODO add the lock mechanism for all of the transition effects + // consider using only one object for one type of transition. + //TODO create the first animation, slide. + dojox.css3.transition.slide = function(node, config){ + + //TODO create the return and set the startState, endState of the return + var ret = new dojox.css3.transition(config); + ret.node = node; + + var startX = "0"; + var endX = "0"; + + if(ret["in"]){ + if(ret.direction === 1){ + startX = "100%"; + }else{ + startX = "-100%"; + } + }else{ + if(ret.direction === 1){ + endX = "-100%"; + }else{ + endX = "100%"; + } + } + + + ret.startState[transitionPrefix + "ransform"]=translateMethodStart+startX+translateMethodEnd; + + ret.endState[transitionPrefix + "ransform"]=translateMethodStart+endX+translateMethodEnd; + + return ret; + }; + + + //fade in/out animation effects + dojox.css3.transition.fade = function(node, config){ + + var ret = new dojox.css3.transition(config); + ret.node = node; + + var startOpacity = "0"; + var endOpacity = "0"; + + if(ret["in"]){ + endOpacity = "1"; + }else{ + startOpacity = "1"; + } + + lang.mixin(ret, { + startState:{ + "opacity": startOpacity + }, + endState:{ + "opacity": endOpacity + } + }); + + return ret; + }; + + //fade in/out animation effects + dojox.css3.transition.flip = function(node, config){ + + var ret = new dojox.css3.transition(config); + ret.node = node; + + if(ret["in"]){ + //Need to set opacity here because Android 2.2 has bug that + //scale(...) in transform does not persist status + lang.mixin(ret,{ + startState:{ + "opacity": "0" + }, + endState:{ + "opacity": "1" + } + }); + ret.startState[transitionPrefix + "ransform"]="scale(0,0.8) skew(0,-30deg)"; + ret.endState[transitionPrefix + "ransform"]="scale(1,1) skew(0,0)"; + }else{ + lang.mixin(ret,{ + startState:{ + "opacity": "1" + }, + endState:{ + "opacity": "0" + } + }); + ret.startState[transitionPrefix + "ransform"]="scale(1,1) skew(0,0)"; + ret.endState[transitionPrefix + "ransform"]="scale(0,0.8) skew(0,30deg)"; + } + + return ret; + }; + + var getWaitingList = function(/*Array*/ nodes){ + var defs = []; + array.forEach(nodes, function(node){ + //check whether the node is under other animation + if(node.id && dojox.css3.transition.playing[node.id]){ + //TODO hook on deferred object in dojox.css3.transition.playing + defs.push(dojox.css3.transition.playing[node.id]); + } + + }); + return new deferredList(defs); + }; + + dojox.css3.transition.getWaitingList = getWaitingList; + + //TODO groupedPlay should ensure the UI update happens when + //all animations end. + //the group player to start multiple animations together + dojox.css3.transition.groupedPlay = function(/*Array*/args){ + //args should be array of dojox.css3.transition + + var animNodes = array.filter(args, function(item){ + return item.node; + }); + + var waitingList = getWaitingList(animNodes); + + //update registry with deferred objects in animations of args. + array.forEach(args, function(item){ + if(item.node.id){ + dojox.css3.transition.playing[item.node.id] = item.deferred; + } + }); + + //TODO wait for all deferred object in deferred list to resolve + dojo.when(waitingList, function(){ + array.forEach(args, function(item){ + //set the start state + item.initState(); + }); + + //Assume the fps of the animation should be higher than 30 fps and + //allow the browser to use one frame's time to redraw so that + //the transition can be started + setTimeout(function(){ + array.forEach(args, function(item){ + item.start(); + }); + }, 33); + }); + }; + + //the chain player to start multiple animations one by one + dojox.css3.transition.chainedPlay = function(/*Array*/args){ + //args should be array of dojox.css3.transition + + var animNodes = array.filter(args, function(item){ + return item.node; + }); + + var waitingList = getWaitingList(animNodes); + + //update registry with deferred objects in animations of args. + array.forEach(args, function(item){ + if(item.node.id){ + dojox.css3.transition.playing[item.node.id] = item.deferred; + } + }); + + dojo.when(waitingList, function(){ + array.forEach(args, function(item){ + //set the start state + item.initState(); + }); + + //chain animations together + for (var i=1, len=args.length; i < len; i++){ + args[i-1].deferred.then(lang.hitch(args[i], function(){ + this.start(); + })); + } + + //Assume the fps of the animation should be higher than 30 fps and + //allow the browser to use one frame's time to redraw so that + //the transition can be started + setTimeout(function(){ + args[0].start(); + }, 33); + }); + }; + + //TODO complete the registry mechanism for animation handling and prevent animation conflicts + dojox.css3.transition.playing = {}; + + return dojox.css3.transition; +}); |
