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-Manager'>/**
19 </span> * @class Ext.fx.Manager
20 * Animation Manager which keeps track of all current animations and manages them on a frame by frame basis.
25 Ext.define('Ext.fx.Manager', {
27 /* Begin Definitions */
31 requires: ['Ext.util.MixedCollection',
32 'Ext.fx.target.Element',
33 'Ext.fx.target.CompositeElement',
34 'Ext.fx.target.Sprite',
35 'Ext.fx.target.CompositeSprite',
36 'Ext.fx.target.Component'],
44 constructor: function() {
45 this.items = Ext.create('Ext.util.MixedCollection');
46 this.mixins.queue.constructor.call(this);
48 // this.requestAnimFrame = (function() {
49 // var raf = window.requestAnimationFrame ||
50 // window.webkitRequestAnimationFrame ||
51 // window.mozRequestAnimationFrame ||
52 // window.oRequestAnimationFrame ||
53 // window.msRequestAnimationFrame;
55 // return function(callback, element) {
60 // return function(callback, element) {
61 // window.setTimeout(callback, Ext.fx.Manager.interval);
67 <span id='Ext-fx-Manager-cfg-interval'> /**
68 </span> * @cfg {Number} interval Default interval in miliseconds to calculate each frame. Defaults to 16ms (~60fps)
72 <span id='Ext-fx-Manager-cfg-forceJS'> /**
73 </span> * @cfg {Boolean} forceJS Turn off to not use CSS3 transitions when they are available
77 // @private Target factory
78 createTarget: function(target) {
80 useCSS3 = !me.forceJS && Ext.supports.Transitions,
86 if (Ext.isString(target)) {
87 target = Ext.get(target);
90 if (target && target.tagName) {
91 target = Ext.get(target);
92 targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
93 me.targets.add(targetObj);
96 if (Ext.isObject(target)) {
99 targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
102 else if (target.isComposite) {
103 targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
106 else if (target.isSprite) {
107 targetObj = Ext.create('Ext.fx.target.Sprite', target);
109 // Draw Sprite Composite
110 else if (target.isCompositeSprite) {
111 targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
114 else if (target.isComponent) {
115 targetObj = Ext.create('Ext.fx.target.Component', target);
117 else if (target.isAnimTarget) {
123 me.targets.add(targetObj);
131 <span id='Ext-fx-Manager-method-addAnim'> /**
132 </span> * Add an Anim to the manager. This is done automatically when an Anim instance is created.
133 * @param {Ext.fx.Anim} anim
135 addAnim: function(anim) {
136 var items = this.items,
141 // if (items.length) {
144 // me.requestAnimFrame(cb);
153 // Start the timer if not already running
154 if (!task && items.length) {
157 interval: this.interval,
160 Ext.TaskManager.start(task);
163 // //Start the timer if not already running
164 // if (!me.task && items.length) {
165 // me.requestAnimFrame(cb);
169 <span id='Ext-fx-Manager-method-removeAnim'> /**
170 </span> * Remove an Anim from the manager. This is done automatically when an Anim ends.
171 * @param {Ext.fx.Anim} anim
173 removeAnim: function(anim) {
174 // this.items.remove(anim);
175 var items = this.items,
178 // Stop the timer if there are no more managed Anims
179 if (task && !items.length) {
180 Ext.TaskManager.stop(task);
185 <span id='Ext-fx-Manager-method-startingFilter'> /**
187 * Filter function to determine which animations need to be started
189 startingFilter: function(o) {
190 return o.paused === false && o.running === false && o.iterations > 0;
193 <span id='Ext-fx-Manager-method-runningFilter'> /**
195 * Filter function to determine which animations are still running
197 runningFilter: function(o) {
198 return o.paused === false && o.running === true && o.isAnimator !== true;
201 <span id='Ext-fx-Manager-method-runner'> /**
203 * Runner function being called each frame
212 // Single timestamp for all animations this interval
213 me.timestamp = new Date();
215 // Start any items not current running
216 items.filterBy(me.startingFilter).each(me.startAnim, me);
218 // Build the new attributes to be applied for all targets in this frame
219 items.filterBy(me.runningFilter).each(me.runAnim, me);
221 // Apply all the pending changes to their targets
222 me.applyPendingAttrs();
225 <span id='Ext-fx-Manager-method-startAnim'> /**
227 * Start the individual animation (initialization)
229 startAnim: function(anim) {
230 anim.start(this.timestamp);
233 <span id='Ext-fx-Manager-method-runAnim'> /**
235 * Run the individual animation for this frame
237 runAnim: function(anim) {
242 targetId = anim.target.getId(),
243 useCSS3 = me.useCSS3 && anim.target.type == 'element',
244 elapsedTime = me.timestamp - anim.startTime,
247 this.collectTargetData(anim, elapsedTime, useCSS3);
249 // For CSS3 animation, we need to immediately set the first frame's attributes without any transition
250 // to get a good initial state, then add the transition properties and set the final attributes.
252 // Flush the collected attributes, without transition
253 anim.target.setAttr(me.targetData[targetId], true);
255 // Add the end frame data
256 me.targetData[targetId] = [];
257 me.collectTargetData(anim, anim.duration, useCSS3);
259 // Pause the animation so runAnim doesn't keep getting called
262 target = anim.target.target;
263 // We only want to attach an event on the last element in a composite
264 if (anim.target.isComposite) {
265 target = anim.target.target.last();
268 // Listen for the transitionend event
270 o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
275 // For JS animation, trigger the lastFrame handler if this is the final frame
276 else if (elapsedTime >= anim.duration) {
277 me.applyPendingAttrs(true);
278 delete me.targetData[targetId];
279 delete me.targetArr[targetId];
284 <span id='Ext-fx-Manager-method-collectTargetData'> /**
285 </span> * Collect target attributes for the given Anim object at the given timestamp
286 * @param {Ext.fx.Anim} anim The Anim instance
287 * @param {Number} timestamp Time after the anim's start time
289 collectTargetData: function(anim, elapsedTime, useCSS3) {
290 var targetId = anim.target.getId(),
291 targetData = this.targetData[targetId],
295 targetData = this.targetData[targetId] = [];
296 this.targetArr[targetId] = anim.target;
300 duration: anim.duration,
301 easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
304 Ext.apply(data.attrs, anim.runAnim(elapsedTime));
305 targetData.push(data);
308 <span id='Ext-fx-Manager-method-applyPendingAttrs'> /**
310 * Apply all pending attribute changes to their targets
312 applyPendingAttrs: function(isLastFrame) {
313 var targetData = this.targetData,
314 targetArr = this.targetArr,
316 for (targetId in targetData) {
317 if (targetData.hasOwnProperty(targetId)) {
318 targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);