//>>built define("dojox/fx/Timeline", ["dojo/_base/lang","dojo/fx/easing","dojo/_base/fx","dojo/dom","./_base","dojo/_base/connect", "dojo/_base/html", "dojo/_base/array","dojo/_base/Color"], function(lang, easingUtil, baseFx, dom, dojoxFx, connectUtil, htmlUtil, arrayUtil, Color){ dojoxFx.animateTimeline = function(/* Object */options, /* DomNode|String */node){ // options: Object // The paramters passed to the timeline animation. Includes: // keys: Array // An array of objects, with style properties and values. // duration: // Duration of the animation in milliseconds. // Defaults to 1000. // node: DomNode // The DomNode or id to be animated. // // summary: // An add-on to dojo.fx that provides the ability to create // a complex property animation based on an array of "keyframes". // description: // The Timeline is a replacement for the default dojo._Line. // Instead of _Line.getValue returning a float between 0-1, // _Timeline.getValue returns an object with all properties and // their current values. // A property does not have to appear in every keyframe. // As in the example below, "height" is transitioned from the first // keyframe to the third. "width" is transitioned from the first // to the second to the third. // Each keyframe can accept the following custom properties: // step: String // The start, finish or percentage that this keyframe represents. // Allowed parameters are: // 0%-100% // from (same as 0%, used to conform with the Webkit animation spec) // to (same as 100%, used to conform with the Webkit animation spec) // ease: String // The string name of a dojo.fx.easing ease. Defaults to "linear". Use // the suffix name of the ease, like: "quadIn", not: "dojo.fx.quadIn". // // example: // | var keys = [ // | { // | step:"0px", // | ease:"quadInOut", // | width:"50px", // | height:"50px", // | },{ // | step:"25%", // | width:"190px" // | },{ // | step:"100%", // | width:"10px", // | height:"200px", // | } // | ]; // | ani = dojox.fx.animateTimeline({keys:keys, duration:2000}, "myDiv").play(); // var _curve = new Timeline(options.keys); var ani = baseFx.animateProperty({ node:dom.byId(node || options.node), duration:options.duration || 1000, properties:_curve._properties, // don't change! This easing is for the timeline, // not individual properties easing:easingUtil.linear, onAnimate: function(v){ //console.log(" ani:", v); } }); connectUtil.connect(ani, "onEnd", function(node){ // Setting the final style. Hiccups in the browser // can cause the animation to lose track. This ensures // that it finishes in the proper location. var sty = ani.curve.getValue(ani.reversed ? 0 : 1); htmlUtil.style(node, sty); }); connectUtil.connect(ani, "beforeBegin", function(){ // remove default curve and replace it with Timeline if(ani.curve){ delete ani.curve; } ani.curve = _curve; _curve.ani = ani; }) return ani; // dojo.Animation } var Timeline = function(/* Array */keys){ // summary: // The dojox.fx._Timeline object from which an instance // is created // tags: // private this.keys = lang.isArray(keys) ? this.flatten(keys) : keys; } Timeline.prototype.flatten = function(keys){ // summary: // An internally used function that converts the keyframes // as used in the example above into a series of key values // which is what is used in the animation parsing. var getPercent = function(str, idx){ if(str == "from"){ return 0; } if(str == "to"){ return 1; } if(str === undefined){ return idx==0 ? 0 : idx / (keys.length - 1) } return parseInt(str, 10) * .01 } var p = {}, o = {}; arrayUtil.forEach(keys, function(k, i){ var step = getPercent(k.step, i); var ease = easingUtil[k.ease] || easingUtil.linear; for(var nm in k){ if(nm == "step" || nm == "ease" || nm == "from" || nm == "to"){ continue; } if(!o[nm]){ o[nm] = { steps:[], values:[], eases:[], ease:ease }; p[nm] = {}; if(!/#/.test(k[nm])){ p[nm].units = o[nm].units = /\D{1,}/.exec(k[nm]).join(""); }else{ p[nm].units = o[nm].units = "isColor"; } } o[nm].eases.push(easingUtil[k.ease || "linear"]); o[nm].steps.push(step); if(p[nm].units == "isColor"){ o[nm].values.push(new Color(k[nm])); }else{ o[nm].values.push(parseInt(/\d{1,}/.exec(k[nm]).join(""))); } if(p[nm].start === undefined){ p[nm].start = o[nm].values[o[nm].values.length-1]; }else{ p[nm].end = o[nm].values[o[nm].values.length-1] } } }); this._properties = p; return o; // Object } Timeline.prototype.getValue = function(/*float*/ p){ // summary: // Replaces the native getValue in dojo.fx.Animation. // Returns an object with all propeties used in the animation // and the property's current value p = this.ani._reversed ? 1-p : p; var o = {}, self = this; var getProp = function(nm, i){ return self._properties[nm].units!="isColor" ? self.keys[nm].values[i] + self._properties[nm].units : self.keys[nm].values[i].toCss(); } for(var nm in this.keys){ var k = this.keys[nm]; for(var i=0; i step){ if(next && p < k.steps[i+1]){ // inbetween steps var end = k.values[i+1]; var beg = k.values[i]; var seg = (1 / (ns - step)) * (p - step); seg = ease(seg); if(beg instanceof Color){ o[nm] = Color.blendColors(beg, end, seg).toCss(false); }else{ var df = end - beg; o[nm] = beg + seg * df + this._properties[nm].units; } break; }else{ // completed keys before 100% o[nm] = getProp(nm, i); } }else if((next && !this.ani._reversed) || (!next && this.ani._reversed)){ o[nm] = getProp(nm, i); } } } return o; // Object }; dojoxFx._Timeline = Timeline; return dojoxFx; });