]>
Commit | Line | Data |
---|---|---|
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 | |
200 | Ext.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 |