]> git.proxmox.com Git - extjs.git/blame - extjs/packages/charts/src/draw/Animator.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / charts / src / draw / Animator.js
CommitLineData
6527f429
DM
1/**\r
2 * @class Ext.draw.Animator\r
3 *\r
4 * Singleton class that manages the animation pool.\r
5 */\r
6Ext.define('Ext.draw.Animator', {\r
7 uses: ['Ext.draw.Draw'],\r
8 singleton: true,\r
9\r
10 frameCallbacks: {},\r
11 frameCallbackId: 0,\r
12 scheduled: 0,\r
13 frameStartTimeOffset: Ext.now(),\r
14 animations: [],\r
15 running: false,\r
16\r
17 /**\r
18 * Cross platform `animationTime` implementation.\r
19 * @return {Number}\r
20 */\r
21 animationTime: function () {\r
22 return Ext.AnimationQueue.frameStartTime - this.frameStartTimeOffset;\r
23 },\r
24\r
25 /**\r
26 * Adds an animated object to the animation pool.\r
27 *\r
28 * @param {Object} animation The animation descriptor to add to the pool.\r
29 */\r
30 add: function (animation) {\r
31 var me = this;\r
32 if (!me.contains(animation)) {\r
33 me.animations.push(animation);\r
34 me.ignite();\r
35 if ('fireEvent' in animation) {\r
36 animation.fireEvent('animationstart', animation);\r
37 }\r
38 }\r
39 },\r
40\r
41 /**\r
42 * Removes an animation from the pool.\r
43 * TODO: This is broken when called within `step` method.\r
44 * @param {Object} animation The animation to remove from the pool.\r
45 */\r
46 remove: function (animation) {\r
47 var me = this,\r
48 animations = me.animations,\r
49 i = 0,\r
50 l = animations.length;\r
51\r
52 for (; i < l; ++i) {\r
53 if (animations[i] === animation) {\r
54 animations.splice(i, 1);\r
55 if ('fireEvent' in animation) {\r
56 animation.fireEvent('animationend', animation);\r
57 }\r
58 return;\r
59 }\r
60 }\r
61 },\r
62\r
63 /**\r
64 * Returns `true` or `false` whether it contains the given animation or not.\r
65 *\r
66 * @param {Object} animation The animation to check for.\r
67 * @return {Boolean}\r
68 */\r
69 contains: function (animation) {\r
70 return Ext.Array.indexOf(this.animations, animation) > -1;\r
71 },\r
72\r
73 /**\r
74 * Returns `true` or `false` whether the pool is empty or not.\r
75 * @return {Boolean}\r
76 */\r
77 empty: function () {\r
78 return this.animations.length === 0;\r
79 },\r
80\r
81 /**\r
82 * Given a frame time it will filter out finished animations from the pool.\r
83 *\r
84 * @param {Number} frameTime The frame's start time, in milliseconds.\r
85 */\r
86 step: function (frameTime) {\r
87 var me = this,\r
88 animations = me.animations,\r
89 animation,\r
90 i = 0,\r
91 ln = animations.length;\r
92\r
93 for (; i < ln; i++) {\r
94 animation = animations[i];\r
95 animation.step(frameTime);\r
96 if (!animation.animating) {\r
97 animations.splice(i, 1);\r
98 i--;\r
99 ln--;\r
100 if (animation.fireEvent) {\r
101 animation.fireEvent('animationend', animation);\r
102 }\r
103 }\r
104 }\r
105 },\r
106\r
107 /**\r
108 * Register a one-time callback that will be called at the next frame.\r
109 * @param {Function/String} callback\r
110 * @param {Object} scope\r
111 * @return {String} The ID of the scheduled callback.\r
112 */\r
113 schedule: function (callback, scope) {\r
114 scope = scope || this;\r
115 var id = 'frameCallback' + (this.frameCallbackId++);\r
116\r
117 if (Ext.isString(callback)) {\r
118 callback = scope[callback];\r
119 }\r
120 Ext.draw.Animator.frameCallbacks[id] = {fn: callback, scope: scope, once: true};\r
121 this.scheduled++;\r
122 Ext.draw.Animator.ignite();\r
123 return id;\r
124 },\r
125\r
126 /**\r
127 * Register a one-time callback that will be called at the next frame,\r
128 * if that callback (with a matching function and scope) isn't already scheduled.\r
129 * @param {Function/String} callback\r
130 * @param {Object} scope\r
131 * @return {String/null} The ID of the scheduled callback or null, if that callback has already been scheduled.\r
132 */\r
133 scheduleIf: function (callback, scope) {\r
134 scope = scope || this;\r
135 var frameCallbacks = Ext.draw.Animator.frameCallbacks,\r
136 cb, id;\r
137\r
138 if (Ext.isString(callback)) {\r
139 callback = scope[callback];\r
140 }\r
141 for (id in frameCallbacks) {\r
142 cb = frameCallbacks[id];\r
143 if (cb.once && cb.fn === callback && cb.scope === scope) {\r
144 return null;\r
145 }\r
146 }\r
147 return this.schedule(callback, scope);\r
148 },\r
149\r
150 /**\r
151 * Cancel a registered one-time callback\r
152 * @param {String} id\r
153 */\r
154 cancel: function (id) {\r
155 if (Ext.draw.Animator.frameCallbacks[id] && Ext.draw.Animator.frameCallbacks[id].once) {\r
156 this.scheduled--;\r
157 delete Ext.draw.Animator.frameCallbacks[id];\r
158 }\r
159 },\r
160\r
161 /**\r
162 * Register a recursive callback that will be called at every frame.\r
163 *\r
164 * @param {Function} callback\r
165 * @param {Object} scope\r
166 * @return {String}\r
167 */\r
168 addFrameCallback: function (callback, scope) {\r
169 scope = scope || this;\r
170 if (Ext.isString(callback)) {\r
171 callback = scope[callback];\r
172 }\r
173 var id = 'frameCallback' + (this.frameCallbackId++);\r
174\r
175 Ext.draw.Animator.frameCallbacks[id] = {fn: callback, scope: scope};\r
176 return id;\r
177 },\r
178\r
179 /**\r
180 * Unregister a recursive callback.\r
181 * @param {String} id\r
182 */\r
183 removeFrameCallback: function (id) {\r
184 delete Ext.draw.Animator.frameCallbacks[id];\r
185 },\r
186\r
187 /**\r
188 * @private\r
189 */\r
190 fireFrameCallbacks: function () {\r
191 var callbacks = this.frameCallbacks,\r
192 id, fn, cb;\r
193\r
194 for (id in callbacks) {\r
195 cb = callbacks[id];\r
196 fn = cb.fn;\r
197 if (Ext.isString(fn)) {\r
198 fn = cb.scope[fn];\r
199 }\r
200\r
201 fn.call(cb.scope);\r
202\r
203 if (callbacks[id] && cb.once) {\r
204 this.scheduled--;\r
205 delete callbacks[id];\r
206 }\r
207 }\r
208 },\r
209\r
210 handleFrame: function() {\r
211 this.step(this.animationTime());\r
212 this.fireFrameCallbacks();\r
213 if (!this.scheduled && this.empty()) {\r
214 Ext.AnimationQueue.stop(this.handleFrame, this);\r
215 this.running = false;\r
216 Ext.draw.Draw.endUpdateIOS();\r
217 }\r
218 },\r
219\r
220 ignite: function() {\r
221 if (!this.running) {\r
222 this.running = true;\r
223 Ext.AnimationQueue.start(this.handleFrame, this);\r
224 Ext.draw.Draw.beginUpdateIOS();\r
225 }\r
226 }\r
227});\r