]> git.proxmox.com Git - extjs.git/blame - extjs/classic/classic/src/util/Animate.js
add extjs 6.0.1 sources
[extjs.git] / extjs / classic / classic / src / util / Animate.js
CommitLineData
6527f429
DM
1/**\r
2 * This animation class is a mixin.\r
3 *\r
4 * Ext.util.Animate provides an API for the creation of animated transitions of properties and styles.\r
5 * This class is used as a mixin and currently applied to {@link Ext.dom.Element}, {@link Ext.CompositeElement},\r
6 * {@link Ext.draw.sprite.Sprite}, {@link Ext.draw.sprite.Composite}, and {@link Ext.Component}. Note that Components\r
7 * have a limited subset of what attributes can be animated such as top, left, x, y, height, width, and\r
8 * opacity (color, paddings, and margins can not be animated).\r
9 *\r
10 * ## Animation Basics\r
11 *\r
12 * All animations require three things - `easing`, `duration`, and `to` (the final end value for each property)\r
13 * you wish to animate. Easing and duration are defaulted values specified below.\r
14 * Easing describes how the intermediate values used during a transition will be calculated.\r
15 * {@link Ext.fx.Anim#easing Easing} allows for a transition to change speed over its duration.\r
16 * You may use the defaults for easing and duration, but you must always set a\r
17 * {@link Ext.fx.Anim#to to} property which is the end value for all animations.\r
18 *\r
19 * Popular element 'to' configurations are:\r
20 *\r
21 * - opacity\r
22 * - x\r
23 * - y\r
24 * - color\r
25 * - height\r
26 * - width\r
27 *\r
28 * Popular sprite 'to' configurations are:\r
29 *\r
30 * - translation\r
31 * - path\r
32 * - scale\r
33 * - stroke\r
34 * - rotation\r
35 *\r
36 * The default duration for animations is 250 (which is a 1/4 of a second). Duration is denoted in\r
37 * milliseconds. Therefore 1 second is 1000, 1 minute would be 60000, and so on. The default easing curve\r
38 * used for all animations is 'ease'. Popular easing functions are included and can be found in {@link Ext.fx.Anim#easing Easing}.\r
39 *\r
40 * For example, a simple animation to fade out an element with a default easing and duration:\r
41 *\r
42 * var p1 = Ext.get('myElementId');\r
43 *\r
44 * p1.animate({\r
45 * to: {\r
46 * opacity: 0\r
47 * }\r
48 * });\r
49 *\r
50 * To make this animation fade out in a tenth of a second:\r
51 *\r
52 * var p1 = Ext.get('myElementId');\r
53 *\r
54 * p1.animate({\r
55 * duration: 100,\r
56 * to: {\r
57 * opacity: 0\r
58 * }\r
59 * });\r
60 *\r
61 * ## Animation Queues\r
62 *\r
63 * By default all animations are added to a queue which allows for animation via a chain-style API.\r
64 * For example, the following code will queue 4 animations which occur sequentially (one right after the other):\r
65 *\r
66 * p1.animate({\r
67 * to: {\r
68 * x: 500\r
69 * }\r
70 * }).animate({\r
71 * to: {\r
72 * y: 150\r
73 * }\r
74 * }).animate({\r
75 * to: {\r
76 * backgroundColor: '#f00' //red\r
77 * }\r
78 * }).animate({\r
79 * to: {\r
80 * opacity: 0\r
81 * }\r
82 * });\r
83 *\r
84 * You can change this behavior by calling the {@link Ext.util.Animate#syncFx syncFx} method and all\r
85 * subsequent animations for the specified target will be run concurrently (at the same time).\r
86 *\r
87 * p1.syncFx(); //this will make all animations run at the same time\r
88 *\r
89 * p1.animate({\r
90 * to: {\r
91 * x: 500\r
92 * }\r
93 * }).animate({\r
94 * to: {\r
95 * y: 150\r
96 * }\r
97 * }).animate({\r
98 * to: {\r
99 * backgroundColor: '#f00' //red\r
100 * }\r
101 * }).animate({\r
102 * to: {\r
103 * opacity: 0\r
104 * }\r
105 * });\r
106 *\r
107 * This works the same as:\r
108 *\r
109 * p1.animate({\r
110 * to: {\r
111 * x: 500,\r
112 * y: 150,\r
113 * backgroundColor: '#f00' //red\r
114 * opacity: 0\r
115 * }\r
116 * });\r
117 *\r
118 * The {@link Ext.util.Animate#stopAnimation stopAnimation} method can be used to stop any\r
119 * currently running animations and clear any queued animations.\r
120 *\r
121 * ## Animation Keyframes\r
122 *\r
123 * You can also set up complex animations with {@link Ext.fx.Anim#keyframes keyframes} which follow the\r
124 * CSS3 Animation configuration pattern. Note rotation, translation, and scaling can only be done for sprites.\r
125 * The previous example can be written with the following syntax:\r
126 *\r
127 * p1.animate({\r
128 * duration: 1000, //one second total\r
129 * keyframes: {\r
130 * 25: { //from 0 to 250ms (25%)\r
131 * x: 0\r
132 * },\r
133 * 50: { //from 250ms to 500ms (50%)\r
134 * y: 0\r
135 * },\r
136 * 75: { //from 500ms to 750ms (75%)\r
137 * backgroundColor: '#f00' //red\r
138 * },\r
139 * 100: { //from 750ms to 1sec\r
140 * opacity: 0\r
141 * }\r
142 * }\r
143 * });\r
144 *\r
145 * ## Animation Events\r
146 *\r
147 * Each animation you create has events for {@link Ext.fx.Anim#beforeanimate beforeanimate},\r
148 * {@link Ext.fx.Anim#afteranimate afteranimate}, and {@link Ext.fx.Anim#lastframe lastframe}.\r
149 * Keyframed animations adds an additional {@link Ext.fx.Animator#keyframe keyframe} event which\r
150 * fires for each keyframe in your animation.\r
151 *\r
152 * All animations support the {@link Ext.util.Observable#listeners listeners} configuration to attact functions to these events.\r
153 *\r
154 * startAnimate: function() {\r
155 * var p1 = Ext.get('myElementId');\r
156 * p1.animate({\r
157 * duration: 100,\r
158 * to: {\r
159 * opacity: 0\r
160 * },\r
161 * listeners: {\r
162 * beforeanimate: function() {\r
163 * // Execute my custom method before the animation\r
164 * this.myBeforeAnimateFn();\r
165 * },\r
166 * afteranimate: function() {\r
167 * // Execute my custom method after the animation\r
168 * this.myAfterAnimateFn();\r
169 * },\r
170 * scope: this\r
171 * });\r
172 * },\r
173 * myBeforeAnimateFn: function() {\r
174 * // My custom logic\r
175 * },\r
176 * myAfterAnimateFn: function() {\r
177 * // My custom logic\r
178 * }\r
179 *\r
180 * Due to the fact that animations run asynchronously, you can determine if an animation is currently\r
181 * running on any target by using the {@link Ext.util.Animate#getActiveAnimation getActiveAnimation}\r
182 * method. This method will return false if there are no active animations or return the currently\r
183 * running {@link Ext.fx.Anim} instance.\r
184 *\r
185 * In this example, we're going to wait for the current animation to finish, then stop any other\r
186 * queued animations before we fade our element's opacity to 0:\r
187 *\r
188 * var curAnim = p1.getActiveAnimation();\r
189 * if (curAnim) {\r
190 * curAnim.on('afteranimate', function() {\r
191 * p1.stopAnimation();\r
192 * p1.animate({\r
193 * to: {\r
194 * opacity: 0\r
195 * }\r
196 * });\r
197 * });\r
198 * }\r
199 */\r
200Ext.define('Ext.util.Animate', {\r
201 mixinId: 'animate',\r
202\r
203 requires: [\r
204 'Ext.fx.Manager', \r
205 'Ext.fx.Anim'\r
206 ],\r
207 \r
208 isAnimate: true,\r
209\r
210 /**\r
211 * Performs custom animation on this object.\r
212 *\r
213 * This method is applicable to both the {@link Ext.Component Component} class and the {@link Ext.draw.sprite.Sprite Sprite}\r
214 * class. It performs animated transitions of certain properties of this object over a specified timeline.\r
215 *\r
216 * ### Animating a {@link Ext.Component Component}\r
217 *\r
218 * When animating a Component, the following properties may be specified in `from`, `to`, and `keyframe` objects:\r
219 *\r
220 * - `x` - The Component's page X position in pixels.\r
221 *\r
222 * - `y` - The Component's page Y position in pixels\r
223 *\r
224 * - `left` - The Component's `left` value in pixels.\r
225 *\r
226 * - `top` - The Component's `top` value in pixels.\r
227 *\r
228 * - `width` - The Component's `width` value in pixels.\r
229 *\r
230 * - `height` - The Component's `height` value in pixels.\r
231 *\r
232 * - `dynamic` - Specify as true to update the Component's layout (if it is a Container) at every frame of the animation.\r
233 * *Use sparingly as laying out on every intermediate size change is an expensive operation.*\r
234 *\r
235 * For example, to animate a Window to a new size, ensuring that its internal layout and any shadow is correct:\r
236 *\r
237 * myWindow = Ext.create('Ext.window.Window', {\r
238 * title: 'Test Component animation',\r
239 * width: 500,\r
240 * height: 300,\r
241 * layout: {\r
242 * type: 'hbox',\r
243 * align: 'stretch'\r
244 * },\r
245 * items: [{\r
246 * title: 'Left: 33%',\r
247 * margin: '5 0 5 5',\r
248 * flex: 1\r
249 * }, {\r
250 * title: 'Left: 66%',\r
251 * margin: '5 5 5 5',\r
252 * flex: 2\r
253 * }]\r
254 * });\r
255 * myWindow.show();\r
256 * myWindow.header.el.on('click', function() {\r
257 * myWindow.animate({\r
258 * to: {\r
259 * width: (myWindow.getWidth() == 500) ? 700 : 500,\r
260 * height: (myWindow.getHeight() == 300) ? 400 : 300\r
261 * }\r
262 * });\r
263 * });\r
264 *\r
265 * For performance reasons, by default, the internal layout is only updated when the Window reaches its final `"to"`\r
266 * size. If dynamic updating of the Window's child Components is required, then configure the animation with\r
267 * `dynamic: true` and the two child items will maintain their proportions during the animation.\r
268 *\r
269 * @param {Object} config Configuration for {@link Ext.fx.Anim}.\r
270 * Note that the {@link Ext.fx.Anim#to to} config is required.\r
271 * @return {Object} this\r
272 */\r
273 animate: function(animObj) {\r
274 var me = this;\r
275 if (Ext.fx.Manager.hasFxBlock(me.id)) {\r
276 return me;\r
277 }\r
278 Ext.fx.Manager.queueFx(new Ext.fx.Anim(me.anim(animObj)));\r
279 return this;\r
280 },\r
281\r
282 /**\r
283 * @private\r
284 * Process the passed fx configuration.\r
285 */\r
286 anim: function(config) {\r
287 if (!Ext.isObject(config)) {\r
288 return (config) ? {} : false;\r
289 }\r
290\r
291 var me = this;\r
292\r
293 if (config.stopAnimation) {\r
294 me.stopAnimation();\r
295 }\r
296\r
297 Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));\r
298\r
299 return Ext.apply({\r
300 target: me,\r
301 paused: true\r
302 }, config);\r
303 },\r
304 \r
305 /**\r
306 * @private\r
307 * Get animation properties\r
308 */\r
309 getAnimationProps: function() {\r
310 var me = this,\r
311 layout = me.layout;\r
312 \r
313 return layout && layout.animate ? layout.animate : {};\r
314 },\r
315\r
316 /**\r
317 * Stops any running effects and clears this object's internal effects queue if it contains any additional effects\r
318 * that haven't started yet.\r
319 * @deprecated 4.0 Replaced by {@link #stopAnimation}\r
320 * @return {Ext.dom.Element} The Element\r
321 * @method\r
322 */\r
323 stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),\r
324\r
325 /**\r
326 * Stops any running effects and clears this object's internal effects queue if it contains any additional effects\r
327 * that haven't started yet.\r
328 * @return {Ext.dom.Element} The Element\r
329 */\r
330 stopAnimation: function() {\r
331 Ext.fx.Manager.stopAnimation(this.id);\r
332 return this;\r
333 },\r
334\r
335 /**\r
336 * Ensures that all effects queued after syncFx is called on this object are run concurrently. This is the opposite\r
337 * of {@link #sequenceFx}.\r
338 * @return {Object} this\r
339 */\r
340 syncFx: function() {\r
341 Ext.fx.Manager.setFxDefaults(this.id, {\r
342 concurrent: true\r
343 });\r
344 return this;\r
345 },\r
346\r
347 /**\r
348 * Ensures that all effects queued after sequenceFx is called on this object are run in sequence. This is the\r
349 * opposite of {@link #syncFx}.\r
350 * @return {Object} this\r
351 */\r
352 sequenceFx: function() {\r
353 Ext.fx.Manager.setFxDefaults(this.id, {\r
354 concurrent: false\r
355 });\r
356 return this;\r
357 },\r
358\r
359 /**\r
360 * @deprecated 4.0 Replaced by {@link #getActiveAnimation}\r
361 * @inheritdoc Ext.util.Animate#getActiveAnimation\r
362 * @method\r
363 */\r
364 hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),\r
365\r
366 /**\r
367 * Returns the current animation if this object has any effects actively running or queued, else returns false.\r
368 * @return {Ext.fx.Anim/Boolean} Anim if element has active effects, else false\r
369 */\r
370 getActiveAnimation: function() {\r
371 return Ext.fx.Manager.getActiveAnimation(this.id);\r
372 }\r
373});\r