Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Anim.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-fx.Anim'>/**
2 </span> * @class Ext.fx.Anim
3  * 
4  * This class manages animation for a specific {@link #target}. The animation allows
5  * animation of various properties on the target, such as size, position, color and others.
6  * 
7  * ## Starting Conditions
8  * The starting conditions for the animation are provided by the {@link #from} configuration.
9  * Any/all of the properties in the {@link #from} configuration can be specified. If a particular
10  * property is not defined, the starting value for that property will be read directly from the target.
11  * 
12  * ## End Conditions
13  * The ending conditions for the animation are provided by the {@link #to} configuration. These mark
14  * the final values once the animations has finished. The values in the {@link #from} can mirror
15  * those in the {@link #to} configuration to provide a starting point.
16  * 
17  * ## Other Options
18  *  - {@link #duration}: Specifies the time period of the animation.
19  *  - {@link #easing}: Specifies the easing of the animation.
20  *  - {@link #iterations}: Allows the animation to repeat a number of times.
21  *  - {@link #alternate}: Used in conjunction with {@link #iterations}, reverses the direction every second iteration.
22  * 
23  * ## Example Code
24  * 
25  *     var myComponent = Ext.create('Ext.Component', {
26  *         renderTo: document.body,
27  *         width: 200,
28  *         height: 200,
29  *         style: 'border: 1px solid red;'
30  *     });
31  *     
32  *     new Ext.fx.Anim({
33  *         target: myComponent,
34  *         duration: 1000,
35  *         from: {
36  *             width: 400 //starting width 400
37  *         },
38  *         to: {
39  *             width: 300, //end width 300
40  *             height: 300 // end width 300
41  *         }
42  *     });
43  */
44 Ext.define('Ext.fx.Anim', {
45
46     /* Begin Definitions */
47
48     mixins: {
49         observable: 'Ext.util.Observable'
50     },
51
52     requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
53
54     /* End Definitions */
55
56     isAnimation: true,
57 <span id='Ext-fx.Anim-cfg-duration'>    /**
58 </span>     * @cfg {Number} duration
59      * Time in milliseconds for a single animation to last. Defaults to 250. If the {@link #iterations} property is
60      * specified, then each animate will take the same duration for each iteration.
61      */
62     duration: 250,
63
64 <span id='Ext-fx.Anim-cfg-delay'>    /**
65 </span>     * @cfg {Number} delay
66      * Time to delay before starting the animation. Defaults to 0.
67      */
68     delay: 0,
69
70     /* private used to track a delayed starting time */
71     delayStart: 0,
72
73 <span id='Ext-fx.Anim-cfg-dynamic'>    /**
74 </span>     * @cfg {Boolean} dynamic
75      * Currently only for Component Animation: Only set a component's outer element size bypassing layouts.  Set to true to do full layouts for every frame of the animation.  Defaults to false.
76      */
77     dynamic: false,
78
79 <span id='Ext-fx.Anim-cfg-easing'>    /**
80 </span>     * @cfg {String} easing
81 This describes how the intermediate values used during a transition will be calculated. It allows for a transition to change
82 speed over its duration. 
83
84          -backIn
85          -backOut
86          -bounceIn
87          -bounceOut
88          -ease
89          -easeIn
90          -easeOut
91          -easeInOut
92          -elasticIn
93          -elasticOut
94          -cubic-bezier(x1, y1, x2, y2)
95
96 Note that cubic-bezier will create a custom easing curve following the CSS3 transition-timing-function specification `{@link http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag}`. The four values specify points P1 and P2 of the curve
97 as (x1, y1, x2, y2). All values must be in the range [0, 1] or the definition is invalid.
98      * @markdown
99      */
100     easing: 'ease',
101
102 <span id='Ext-fx.Anim-cfg-keyframes'>     /**
103 </span>      * @cfg {Object} keyframes
104       * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'
105       * is considered '100%'.&lt;b&gt;Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using
106       * &quot;from&quot; or &quot;to&quot;&lt;/b&gt;.  A keyframe declaration without these keyframe selectors is invalid and will not be available for
107       * animation.  The keyframe declaration for a keyframe rule consists of properties and values. Properties that are unable to
108       * be animated are ignored in these rules, with the exception of 'easing' which can be changed at each keyframe. For example:
109  &lt;pre&gt;&lt;code&gt;
110 keyframes : {
111     '0%': {
112         left: 100
113     },
114     '40%': {
115         left: 150
116     },
117     '60%': {
118         left: 75
119     },
120     '100%': {
121         left: 100
122     }
123 }
124  &lt;/code&gt;&lt;/pre&gt;
125       */
126
127 <span id='Ext-fx.Anim-property-damper'>    /**
128 </span>     * @private
129      */
130     damper: 1,
131
132 <span id='Ext-fx.Anim-property-bezierRE'>    /**
133 </span>     * @private
134      */
135     bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
136
137 <span id='Ext-fx.Anim-cfg-reverse'>    /**
138 </span>     * Run the animation from the end to the beginning
139      * Defaults to false.
140      * @cfg {Boolean} reverse
141      */
142     reverse: false,
143
144 <span id='Ext-fx.Anim-property-running'>    /**
145 </span>     * Flag to determine if the animation has started
146      * @property running
147      * @type boolean
148      */
149     running: false,
150
151 <span id='Ext-fx.Anim-property-paused'>    /**
152 </span>     * Flag to determine if the animation is paused. Only set this to true if you need to
153      * keep the Anim instance around to be unpaused later; otherwise call {@link #end}.
154      * @property paused
155      * @type boolean
156      */
157     paused: false,
158
159 <span id='Ext-fx.Anim-cfg-iterations'>    /**
160 </span>     * Number of times to execute the animation. Defaults to 1.
161      * @cfg {int} iterations
162      */
163     iterations: 1,
164
165 <span id='Ext-fx.Anim-cfg-alternate'>    /**
166 </span>     * Used in conjunction with iterations to reverse the animation each time an iteration completes.
167      * @cfg {Boolean} alternate
168      * Defaults to false.
169      */
170     alternate: false,
171
172 <span id='Ext-fx.Anim-property-currentIteration'>    /**
173 </span>     * Current iteration the animation is running.
174      * @property currentIteration
175      * @type int
176      */
177     currentIteration: 0,
178
179 <span id='Ext-fx.Anim-property-startTime'>    /**
180 </span>     * Starting time of the animation.
181      * @property startTime
182      * @type Date
183      */
184     startTime: 0,
185
186 <span id='Ext-fx.Anim-property-propHandlers'>    /**
187 </span>     * Contains a cache of the interpolators to be used.
188      * @private
189      * @property propHandlers
190      * @type Object
191      */
192
193 <span id='Ext-fx.Anim-cfg-target'>    /**
194 </span>     * @cfg {String/Object} target
195      * The {@link Ext.fx.target.Target} to apply the animation to.  This should only be specified when creating an Ext.fx.Anim directly.
196      * The target does not need to be a {@link Ext.fx.target.Target} instance, it can be the underlying object. For example, you can
197      * pass a Component, Element or Sprite as the target and the Anim will create the appropriate {@link Ext.fx.target.Target} object
198      * automatically.
199      */
200
201 <span id='Ext-fx.Anim-cfg-from'>    /**
202 </span>     * @cfg {Object} from
203      * An object containing property/value pairs for the beginning of the animation.  If not specified, the current state of the
204      * Ext.fx.target will be used. For example:
205 &lt;pre&gt;&lt;code&gt;
206 from : {
207     opacity: 0,       // Transparent
208     color: '#ffffff', // White
209     left: 0
210 }
211 &lt;/code&gt;&lt;/pre&gt;
212      */
213
214 <span id='Ext-fx.Anim-cfg-to'>    /**
215 </span>     * @cfg {Object} to
216      * An object containing property/value pairs for the end of the animation. For example:
217  &lt;pre&gt;&lt;code&gt;
218  to : {
219      opacity: 1,       // Opaque
220      color: '#00ff00', // Green
221      left: 500
222  }
223  &lt;/code&gt;&lt;/pre&gt;
224      */
225
226     // @private
227     constructor: function(config) {
228         var me = this;
229         config = config || {};
230         // If keyframes are passed, they really want an Animator instead.
231         if (config.keyframes) {
232             return Ext.create('Ext.fx.Animator', config);
233         }
234         config = Ext.apply(me, config);
235         if (me.from === undefined) {
236             me.from = {};
237         }
238         me.propHandlers = {};
239         me.config = config;
240         me.target = Ext.fx.Manager.createTarget(me.target);
241         me.easingFn = Ext.fx.Easing[me.easing];
242         me.target.dynamic = me.dynamic;
243
244         // If not a pre-defined curve, try a cubic-bezier
245         if (!me.easingFn) {
246             me.easingFn = String(me.easing).match(me.bezierRE);
247             if (me.easingFn &amp;&amp; me.easingFn.length == 5) {
248                 var curve = me.easingFn;
249                 me.easingFn = Ext.fx.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
250             }
251         }
252         me.id = Ext.id(null, 'ext-anim-');
253         Ext.fx.Manager.addAnim(me);
254         me.addEvents(
255 <span id='Ext-fx.Anim-event-beforeanimate'>            /**
256 </span>             * @event beforeanimate
257              * Fires before the animation starts. A handler can return false to cancel the animation.
258              * @param {Ext.fx.Anim} this
259              */
260             'beforeanimate',
261 <span id='Ext-fx.Anim-event-afteranimate'>             /**
262 </span>              * @event afteranimate
263               * Fires when the animation is complete.
264               * @param {Ext.fx.Anim} this
265               * @param {Date} startTime
266               */
267             'afteranimate',
268 <span id='Ext-fx.Anim-event-lastframe'>             /**
269 </span>              * @event lastframe
270               * Fires when the animation's last frame has been set.
271               * @param {Ext.fx.Anim} this
272               * @param {Date} startTime
273               */
274             'lastframe'
275         );
276         me.mixins.observable.constructor.call(me, config);
277         if (config.callback) {
278             me.on('afteranimate', config.callback, config.scope);
279         }
280         return me;
281     },
282
283 <span id='Ext-fx.Anim-method-setAttr'>    /**
284 </span>     * @private
285      * Helper to the target
286      */
287     setAttr: function(attr, value) {
288         return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
289     },
290
291     /*
292      * @private
293      * Set up the initial currentAttrs hash.
294      */
295     initAttrs: function() {
296         var me = this,
297             from = me.from,
298             to = me.to,
299             initialFrom = me.initialFrom || {},
300             out = {},
301             start, end, propHandler, attr;
302
303         for (attr in to) {
304             if (to.hasOwnProperty(attr)) {
305                 start = me.target.getAttr(attr, from[attr]);
306                 end = to[attr];
307                 // Use default (numeric) property handler
308                 if (!Ext.fx.PropertyHandler[attr]) {
309                     if (Ext.isObject(end)) {
310                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
311                     } else {
312                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
313                     }
314                 }
315                 // Use custom handler
316                 else {
317                     propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
318                 }
319                 out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
320             }
321         }
322         me.currentAttrs = out;
323     },
324
325     /*
326      * @private
327      * Fires beforeanimate and sets the running flag.
328      */
329     start: function(startTime) {
330         var me = this,
331             delay = me.delay,
332             delayStart = me.delayStart,
333             delayDelta;
334         if (delay) {
335             if (!delayStart) {
336                 me.delayStart = startTime;
337                 return;
338             }
339             else {
340                 delayDelta = startTime - delayStart;
341                 if (delayDelta &lt; delay) {
342                     return;
343                 }
344                 else {
345                     // Compensate for frame delay;
346                     startTime = new Date(delayStart.getTime() + delay);
347                 }
348             }
349         }
350         if (me.fireEvent('beforeanimate', me) !== false) {
351             me.startTime = startTime;
352             if (!me.paused &amp;&amp; !me.currentAttrs) {
353                 me.initAttrs();
354             }
355             me.running = true;
356         }
357     },
358
359     /*
360      * @private
361      * Calculate attribute value at the passed timestamp.
362      * @returns a hash of the new attributes.
363      */
364     runAnim: function(elapsedTime) {
365         var me = this,
366             attrs = me.currentAttrs,
367             duration = me.duration,
368             easingFn = me.easingFn,
369             propHandlers = me.propHandlers,
370             ret = {},
371             easing, values, attr, lastFrame;
372
373         if (elapsedTime &gt;= duration) {
374             elapsedTime = duration;
375             lastFrame = true;
376         }
377         if (me.reverse) {
378             elapsedTime = duration - elapsedTime;
379         }
380
381         for (attr in attrs) {
382             if (attrs.hasOwnProperty(attr)) {
383                 values = attrs[attr];
384                 easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
385                 ret[attr] = propHandlers[attr].set(values, easing);
386             }
387         }
388         return ret;
389     },
390
391     /*
392      * @private
393      * Perform lastFrame cleanup and handle iterations
394      * @returns a hash of the new attributes.
395      */
396     lastFrame: function() {
397         var me = this,
398             iter = me.iterations,
399             iterCount = me.currentIteration;
400
401         iterCount++;
402         if (iterCount &lt; iter) {
403             if (me.alternate) {
404                 me.reverse = !me.reverse;
405             }
406             me.startTime = new Date();
407             me.currentIteration = iterCount;
408             // Turn off paused for CSS3 Transitions
409             me.paused = false;
410         }
411         else {
412             me.currentIteration = 0;
413             me.end();
414             me.fireEvent('lastframe', me, me.startTime);
415         }
416     },
417
418     /*
419      * Fire afteranimate event and end the animation. Usually called automatically when the
420      * animation reaches its final frame, but can also be called manually to pre-emptively
421      * stop and destroy the running animation.
422      */
423     end: function() {
424         var me = this;
425         me.startTime = 0;
426         me.paused = false;
427         me.running = false;
428         Ext.fx.Manager.removeAnim(me);
429         me.fireEvent('afteranimate', me, me.startTime);
430     }
431 });
432 // Set flag to indicate that Fx is available. Class might not be available immediately.
433 Ext.enableFx = true;
434 </pre></pre></body></html>