4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../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
22 This class is used to run keyframe based animations, which follows the CSS3 based animation structure.
23 Keyframe animations differ from typical from/to animations in that they offer the ability to specify values
24 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.
34 In the example below, we modify the values of the element at each fifth throughout the animation.
36 Ext.create('Ext.fx.Animator', {
37 target: Ext.getBody().createChild({
41 'background-color': 'red'
44 duration: 10000, // 10 seconds
48 backgroundColor: 'FF0000'
56 backgroundColor: '0000FF'
68 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
138 <span id='Ext-fx-Animator-property-running'> /**
139 </span> * Flag to determine if the animation has started
145 <span id='Ext-fx-Animator-property-paused'> /**
146 </span> * Flag to determine if the animation is paused. Only set this to true if you need to
147 * keep the Anim instance around to be unpaused later; otherwise call {@link #end}.
153 <span id='Ext-fx-Animator-property-damper'> /**
158 <span id='Ext-fx-Animator-cfg-iterations'> /**
159 </span> * @cfg {Number} iterations
160 * Number of times to execute the animation. Defaults to 1.
164 <span id='Ext-fx-Animator-property-currentIteration'> /**
165 </span> * Current iteration the animation is running.
166 * @property currentIteration
171 <span id='Ext-fx-Animator-property-keyframeStep'> /**
172 </span> * Current keyframe step of the animation.
173 * @property keyframeStep
178 <span id='Ext-fx-Animator-property-animKeyFramesRE'> /**
181 animKeyFramesRE: /^(from|to|\d+%?)$/,
183 <span id='Ext-fx-Animator-cfg-target'> /**
184 </span> * @cfg {Ext.fx.target} target
185 * The Ext.fx.target to apply the animation to. If not specified during initialization, this can be passed to the applyAnimator
186 * method to apply the same animation to many targets.
189 <span id='Ext-fx-Animator-cfg-keyframes'> /**
190 </span> * @cfg {Object} keyframes
191 * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'
192 * is considered '100%'.<b>Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using
193 * "from" or "to"</b>. A keyframe declaration without these keyframe selectors is invalid and will not be available for
194 * animation. The keyframe declaration for a keyframe rule consists of properties and values. Properties that are unable to
195 * be animated are ignored in these rules, with the exception of 'easing' which can be changed at each keyframe. For example:
196 <pre><code>
211 </code></pre>
213 constructor: function(config) {
215 config = Ext.apply(me, config || {});
217 me.id = Ext.id(null, 'ext-animator-');
219 <span id='Ext-fx-Animator-event-beforeanimate'> /**
220 </span> * @event beforeanimate
221 * Fires before the animation starts. A handler can return false to cancel the animation.
222 * @param {Ext.fx.Animator} this
225 <span id='Ext-fx-Animator-event-keyframe'> /**
226 </span> * @event keyframe
227 * Fires at each keyframe.
228 * @param {Ext.fx.Animator} this
229 * @param {Number} keyframe step number
232 <span id='Ext-fx-Animator-event-afteranimate'> /**
233 </span> * @event afteranimate
234 * Fires when the animation is complete.
235 * @param {Ext.fx.Animator} this
236 * @param {Date} startTime
240 me.mixins.observable.constructor.call(me, config);
242 me.createTimeline(me.keyframes);
244 me.applyAnimator(me.target);
245 Ext.fx.Manager.addAnim(me);
249 <span id='Ext-fx-Animator-method-sorter'> /**
252 sorter: function (a, b) {
253 return a.pct - b.pct;
256 <span id='Ext-fx-Animator-method-createTimeline'> /**
258 * Takes the given keyframe configuration object and converts it into an ordered array with the passed attributes per keyframe
259 * or applying the 'to' configuration to all keyframes. Also calculates the proper animation duration per keyframe.
261 createTimeline: function(keyframes) {
265 duration = me.duration,
266 prevMs, ms, i, ln, pct, anim, nextAnim, attr;
268 for (pct in keyframes) {
269 if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
270 attr = {attrs: Ext.apply(keyframes[pct], to)};
271 // CSS3 spec allow for from/to to be specified.
272 if (pct == "from") {
275 else if (pct == "to") {
278 // convert % values into integers
279 attr.pct = parseInt(pct, 10);
283 // Sort by pct property
284 Ext.Array.sort(attrs, me.sorter);
286 //if (attrs[0].pct) {
287 // attrs.unshift({pct: 0, attrs: element.attrs});
291 for (i = 0; i < ln; i++) {
292 prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
293 ms = duration * (attrs[i].pct / 100);
295 duration: ms - prevMs,
296 attrs: attrs[i].attrs
301 <span id='Ext-fx-Animator-property-applyAnimator'> /**
302 </span> * Applies animation to the Ext.fx.target
305 * @type string/object
307 applyAnimator: function(target) {
310 timeline = me.timeline,
311 reverse = me.reverse,
312 ln = timeline.length,
313 anim, easing, damper, initial, attrs, lastAttrs, i;
315 if (me.fireEvent('beforeanimate', me) !== false) {
316 for (i = 0; i < ln; i++) {
319 easing = attrs.easing || me.easing;
320 damper = attrs.damper || me.damper;
323 anim = Ext.create('Ext.fx.Anim', {
327 duration: anim.duration,
333 me.animations = anims;
334 me.target = anim.target;
335 for (i = 0; i < ln - 1; i++) {
337 anim.nextAnim = anims[i + 1];
338 anim.on('afteranimate', function() {
339 this.nextAnim.paused = false;
341 anim.on('afteranimate', function() {
342 this.fireEvent('keyframe', this, ++this.keyframeStep);
345 anims[ln - 1].on('afteranimate', function() {
353 * Fires beforeanimate and sets the running flag.
355 start: function(startTime) {
358 delayStart = me.delayStart,
362 me.delayStart = startTime;
366 delayDelta = startTime - delayStart;
367 if (delayDelta < delay) {
371 // Compensate for frame delay;
372 startTime = new Date(delayStart.getTime() + delay);
376 if (me.fireEvent('beforeanimate', me) !== false) {
377 me.startTime = startTime;
379 me.animations[me.keyframeStep].paused = false;
385 * Perform lastFrame cleanup and handle iterations
386 * @returns a hash of the new attributes.
388 lastFrame: function() {
390 iter = me.iterations,
391 iterCount = me.currentIteration;
394 if (iterCount < iter) {
395 me.startTime = new Date();
396 me.currentIteration = iterCount;
398 me.applyAnimator(me.target);
399 me.animations[me.keyframeStep].paused = false;
402 me.currentIteration = 0;
408 * Fire afteranimate event and end the animation. Usually called automatically when the
409 * animation reaches its final frame, but can also be called manually to pre-emptively
410 * stop and destroy the running animation.
414 me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);