4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-fx-Animator'>/**
19 </span> * @class Ext.fx.Animator
21 * This class is used to run keyframe based animations, which follows the CSS3 based animation structure.
22 * Keyframe animations differ from typical from/to animations in that they offer the ability to specify values
23 * at various points throughout the animation.
27 * The {@link #keyframes} option is the most important part of specifying an animation when using this
28 * class. A key frame is a point in a particular animation. We represent this as a percentage of the
29 * total animation duration. At each key frame, we can specify the target values at that time. Note that
30 * you *must* specify the values at 0% and 100%, the start and ending values. There is also a {@link #keyframe}
31 * event that fires after each key frame is reached.
35 * In the example below, we modify the values of the element at each fifth throughout the animation.
38 * Ext.create('Ext.fx.Animator', {
39 * target: Ext.getBody().createChild({
43 * 'background-color': 'red'
46 * duration: 10000, // 10 seconds
50 * backgroundColor: 'FF0000'
58 * backgroundColor: '0000FF'
70 * backgroundColor: '00FF00'
75 Ext.define('Ext.fx.Animator', {
77 /* Begin Definitions */
80 observable: 'Ext.util.Observable'
83 requires: ['Ext.fx.Manager'],
89 <span id='Ext-fx-Animator-cfg-duration'> /**
90 </span> * @cfg {Number} duration
91 * Time in milliseconds for the animation to last. Defaults to 250.
95 <span id='Ext-fx-Animator-cfg-delay'> /**
96 </span> * @cfg {Number} delay
97 * Time to delay before starting the animation. Defaults to 0.
101 /* private used to track a delayed starting time */
104 <span id='Ext-fx-Animator-cfg-dynamic'> /**
105 </span> * @cfg {Boolean} dynamic
106 * 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.
110 <span id='Ext-fx-Animator-cfg-easing'> /**
111 </span> * @cfg {String} easing
113 * This describes how the intermediate values used during a transition will be calculated. It allows for a transition to change
114 * speed over its duration.
126 * - cubic-bezier(x1, y1, x2, y2)
128 * Note that cubic-bezier will create a custom easing curve following the CSS3 [transition-timing-function][0]
129 * specification. The four values specify points P1 and P2 of the curve as (x1, y1, x2, y2). All values must
130 * be in the range [0, 1] or the definition is invalid.
132 * [0]: http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag
136 <span id='Ext-fx-Animator-property-running'> /**
137 </span> * Flag to determine if the animation has started
143 <span id='Ext-fx-Animator-property-paused'> /**
144 </span> * Flag to determine if the animation is paused. Only set this to true if you need to
145 * keep the Anim instance around to be unpaused later; otherwise call {@link #end}.
151 <span id='Ext-fx-Animator-property-damper'> /**
156 <span id='Ext-fx-Animator-cfg-iterations'> /**
157 </span> * @cfg {Number} iterations
158 * Number of times to execute the animation. Defaults to 1.
162 <span id='Ext-fx-Animator-property-currentIteration'> /**
163 </span> * Current iteration the animation is running.
164 * @property currentIteration
169 <span id='Ext-fx-Animator-property-keyframeStep'> /**
170 </span> * Current keyframe step of the animation.
171 * @property keyframeStep
176 <span id='Ext-fx-Animator-property-animKeyFramesRE'> /**
179 animKeyFramesRE: /^(from|to|\d+%?)$/,
181 <span id='Ext-fx-Animator-cfg-target'> /**
182 </span> * @cfg {Ext.fx.target.Target} target
183 * The Ext.fx.target to apply the animation to. If not specified during initialization, this can be passed to the applyAnimator
184 * method to apply the same animation to many targets.
187 <span id='Ext-fx-Animator-cfg-keyframes'> /**
188 </span> * @cfg {Object} keyframes
189 * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'
190 * is considered '100%'.<b>Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using
191 * "from" or "to"</b>. A keyframe declaration without these keyframe selectors is invalid and will not be available for
192 * animation. The keyframe declaration for a keyframe rule consists of properties and values. Properties that are unable to
193 * be animated are ignored in these rules, with the exception of 'easing' which can be changed at each keyframe. For example:
194 <pre><code>
209 </code></pre>
211 constructor: function(config) {
213 config = Ext.apply(me, config || {});
215 me.id = Ext.id(null, 'ext-animator-');
217 <span id='Ext-fx-Animator-event-beforeanimate'> /**
218 </span> * @event beforeanimate
219 * Fires before the animation starts. A handler can return false to cancel the animation.
220 * @param {Ext.fx.Animator} this
223 <span id='Ext-fx-Animator-event-keyframe'> /**
224 </span> * @event keyframe
225 * Fires at each keyframe.
226 * @param {Ext.fx.Animator} this
227 * @param {Number} keyframe step number
230 <span id='Ext-fx-Animator-event-afteranimate'> /**
231 </span> * @event afteranimate
232 * Fires when the animation is complete.
233 * @param {Ext.fx.Animator} this
234 * @param {Date} startTime
238 me.mixins.observable.constructor.call(me, config);
240 me.createTimeline(me.keyframes);
242 me.applyAnimator(me.target);
243 Ext.fx.Manager.addAnim(me);
247 <span id='Ext-fx-Animator-method-sorter'> /**
250 sorter: function (a, b) {
251 return a.pct - b.pct;
254 <span id='Ext-fx-Animator-method-createTimeline'> /**
256 * Takes the given keyframe configuration object and converts it into an ordered array with the passed attributes per keyframe
257 * or applying the 'to' configuration to all keyframes. Also calculates the proper animation duration per keyframe.
259 createTimeline: function(keyframes) {
263 duration = me.duration,
264 prevMs, ms, i, ln, pct, anim, nextAnim, attr;
266 for (pct in keyframes) {
267 if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
268 attr = {attrs: Ext.apply(keyframes[pct], to)};
269 // CSS3 spec allow for from/to to be specified.
270 if (pct == "from") {
273 else if (pct == "to") {
276 // convert % values into integers
277 attr.pct = parseInt(pct, 10);
281 // Sort by pct property
282 Ext.Array.sort(attrs, me.sorter);
284 //if (attrs[0].pct) {
285 // attrs.unshift({pct: 0, attrs: element.attrs});
289 for (i = 0; i < ln; i++) {
290 prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
291 ms = duration * (attrs[i].pct / 100);
293 duration: ms - prevMs,
294 attrs: attrs[i].attrs
299 <span id='Ext-fx-Animator-property-applyAnimator'> /**
300 </span> * Applies animation to the Ext.fx.target
303 * @type String/Object
305 applyAnimator: function(target) {
308 timeline = me.timeline,
309 reverse = me.reverse,
310 ln = timeline.length,
311 anim, easing, damper, initial, attrs, lastAttrs, i;
313 if (me.fireEvent('beforeanimate', me) !== false) {
314 for (i = 0; i < ln; i++) {
317 easing = attrs.easing || me.easing;
318 damper = attrs.damper || me.damper;
321 anim = Ext.create('Ext.fx.Anim', {
325 duration: anim.duration,
331 me.animations = anims;
332 me.target = anim.target;
333 for (i = 0; i < ln - 1; i++) {
335 anim.nextAnim = anims[i + 1];
336 anim.on('afteranimate', function() {
337 this.nextAnim.paused = false;
339 anim.on('afteranimate', function() {
340 this.fireEvent('keyframe', this, ++this.keyframeStep);
343 anims[ln - 1].on('afteranimate', function() {
349 <span id='Ext-fx-Animator-method-start'> /**
351 * Fires beforeanimate and sets the running flag.
353 start: function(startTime) {
356 delayStart = me.delayStart,
360 me.delayStart = startTime;
364 delayDelta = startTime - delayStart;
365 if (delayDelta < delay) {
369 // Compensate for frame delay;
370 startTime = new Date(delayStart.getTime() + delay);
374 if (me.fireEvent('beforeanimate', me) !== false) {
375 me.startTime = startTime;
377 me.animations[me.keyframeStep].paused = false;
381 <span id='Ext-fx-Animator-method-lastFrame'> /**
383 * Perform lastFrame cleanup and handle iterations
384 * @returns a hash of the new attributes.
386 lastFrame: function() {
388 iter = me.iterations,
389 iterCount = me.currentIteration;
392 if (iterCount < iter) {
393 me.startTime = new Date();
394 me.currentIteration = iterCount;
396 me.applyAnimator(me.target);
397 me.animations[me.keyframeStep].paused = false;
400 me.currentIteration = 0;
405 <span id='Ext-fx-Animator-method-end'> /**
406 </span> * Fire afteranimate event and end the animation. Usually called automatically when the
407 * animation reaches its final frame, but can also be called manually to pre-emptively
408 * stop and destroy the running animation.
412 me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);