Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / ext-base-anim.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">/*!
9  * Ext JS Library 3.0.3
10  * Copyright(c) 2006-2009 Ext JS, LLC
11  * licensing@extjs.com
12  * http://www.extjs.com/license
13  */
14 (function(){    \r
15     var EXTLIB = Ext.lib,\r
16         noNegatives = /width|height|opacity|padding/i,\r
17         offsetAttribute = /^((width|height)|(top|left))$/,\r
18         defaultUnit = /width|height|top$|bottom$|left$|right$/i,\r
19         offsetUnit =  /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,\r
20         isset = function(v){\r
21             return typeof v !== 'undefined';\r
22         },\r
23         now = function(){\r
24             return new Date();    \r
25         };\r
26         \r
27     EXTLIB.Anim = {\r
28         motion : function(el, args, duration, easing, cb, scope) {\r
29             return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);\r
30         },\r
31 \r
32         run : function(el, args, duration, easing, cb, scope, type) {\r
33             type = type || Ext.lib.AnimBase;\r
34             if (typeof easing == "string") {\r
35                 easing = Ext.lib.Easing[easing];\r
36             }\r
37             var anim = new type(el, args, duration, easing);\r
38             anim.animateX(function() {\r
39                 if(Ext.isFunction(cb)){\r
40                     cb.call(scope);\r
41                 }\r
42             });\r
43             return anim;\r
44         }\r
45     };\r
46     \r
47     EXTLIB.AnimBase = function(el, attributes, duration, method) {\r
48         if (el) {\r
49             this.init(el, attributes, duration, method);\r
50         }\r
51     };\r
52 \r
53     EXTLIB.AnimBase.prototype = {\r
54         doMethod: function(attr, start, end) {\r
55             var me = this;\r
56             return me.method(me.curFrame, start, end - start, me.totalFrames);\r
57         },\r
58 \r
59 \r
60         setAttr: function(attr, val, unit) {\r
61             if (noNegatives.test(attr) && val < 0) {\r
62                 val = 0;\r
63             }\r
64             Ext.fly(this.el, '_anim').setStyle(attr, val + unit);\r
65         },\r
66 \r
67 \r
68         getAttr: function(attr) {\r
69             var el = Ext.fly(this.el),\r
70                 val = el.getStyle(attr),\r
71                 a = offsetAttribute.exec(attr) || []\r
72 \r
73             if (val !== 'auto' && !offsetUnit.test(val)) {\r
74                 return parseFloat(val);\r
75             }\r
76 \r
77             return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;\r
78         },\r
79 \r
80 \r
81         getDefaultUnit: function(attr) {\r
82             return defaultUnit.test(attr) ? 'px' : '';\r
83         },\r
84 \r
85         animateX : function(callback, scope) {\r
86             var me = this,\r
87                 f = function() {\r
88                 me.onComplete.removeListener(f);\r
89                 if (Ext.isFunction(callback)) {\r
90                     callback.call(scope || me, me);\r
91                 }\r
92             };\r
93             me.onComplete.addListener(f, me);\r
94             me.animate();\r
95         },\r
96 \r
97 \r
98         setRunAttr: function(attr) {            \r
99             var me = this,\r
100                 a = this.attributes[attr],\r
101                 to = a.to,\r
102                 by = a.by,\r
103                 from = a.from,\r
104                 unit = a.unit,\r
105                 ra = (this.runAttrs[attr] = {}),\r
106                 end;\r
107 \r
108             if (!isset(to) && !isset(by)){\r
109                 return false;\r
110             }\r
111 \r
112             var start = isset(from) ? from : me.getAttr(attr);\r
113             if (isset(to)) {\r
114                 end = to;\r
115             }else if(isset(by)) {\r
116                 if (Ext.isArray(start)){\r
117                     end = [];\r
118                     Ext.each(start, function(v, i){\r
119                         end[i] = v + by[i];\r
120                     });\r
121                 }else{\r
122                     end = start + by;\r
123                 }\r
124             }\r
125 \r
126             Ext.apply(ra, {\r
127                 start: start,\r
128                 end: end,\r
129                 unit: isset(unit) ? unit : me.getDefaultUnit(attr)\r
130             });\r
131         },\r
132 \r
133 \r
134         init: function(el, attributes, duration, method) {\r
135             var me = this,\r
136                 actualFrames = 0,\r
137                 mgr = EXTLIB.AnimMgr;\r
138                 \r
139             Ext.apply(me, {\r
140                 isAnimated: false,\r
141                 startTime: null,\r
142                 el: Ext.getDom(el),\r
143                 attributes: attributes || {},\r
144                 duration: duration || 1,\r
145                 method: method || EXTLIB.Easing.easeNone,\r
146                 useSec: true,\r
147                 curFrame: 0,\r
148                 totalFrames: mgr.fps,\r
149                 runAttrs: {},\r
150                 animate: function(){\r
151                     var me = this,\r
152                         d = me.duration;\r
153                     \r
154                     if(me.isAnimated){\r
155                         return false;\r
156                     }\r
157 \r
158                     me.curFrame = 0;\r
159                     me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;\r
160                     mgr.registerElement(me); \r
161                 },\r
162                 \r
163                 stop: function(finish){\r
164                     var me = this;\r
165                 \r
166                     if(finish){\r
167                         me.curFrame = me.totalFrames;\r
168                         me._onTween.fire();\r
169                     }\r
170                     mgr.stop(me);\r
171                 }\r
172             });\r
173 \r
174             var onStart = function(){\r
175                 var me = this,\r
176                     attr;\r
177                 \r
178                 me.onStart.fire();\r
179                 me.runAttrs = {};\r
180                 for(attr in this.attributes){\r
181                     this.setRunAttr(attr);\r
182                 }\r
183 \r
184                 me.isAnimated = true;\r
185                 me.startTime = now();\r
186                 actualFrames = 0;\r
187             };\r
188 \r
189 \r
190             var onTween = function(){\r
191                 var me = this;\r
192 \r
193                 me.onTween.fire({\r
194                     duration: now() - me.startTime,\r
195                     curFrame: me.curFrame\r
196                 });\r
197 \r
198                 var ra = me.runAttrs;\r
199                 for (var attr in ra) {\r
200                     this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);\r
201                 }\r
202 \r
203                 ++actualFrames;\r
204             };\r
205 \r
206             var onComplete = function() {\r
207                 var me = this,\r
208                     actual = (now() - me.startTime) / 1000,\r
209                     data = {\r
210                         duration: actual,\r
211                         frames: actualFrames,\r
212                         fps: actualFrames / actual\r
213                     };\r
214 \r
215                 me.isAnimated = false;\r
216                 actualFrames = 0;\r
217                 me.onComplete.fire(data);\r
218             };\r
219 \r
220             me.onStart = new Ext.util.Event(me);\r
221             me.onTween = new Ext.util.Event(me);            \r
222             me.onComplete = new Ext.util.Event(me);\r
223             (me._onStart = new Ext.util.Event(me)).addListener(onStart);\r
224             (me._onTween = new Ext.util.Event(me)).addListener(onTween);\r
225             (me._onComplete = new Ext.util.Event(me)).addListener(onComplete); \r
226         }\r
227     };\r
228 \r
229 \r
230     Ext.lib.AnimMgr = new function() {\r
231         var me = this,\r
232             thread = null,\r
233             queue = [],\r
234             tweenCount = 0;\r
235 \r
236 \r
237         Ext.apply(me, {\r
238             fps: 1000,\r
239             delay: 1,\r
240             registerElement: function(tween){\r
241                 queue.push(tween);\r
242                 ++tweenCount;\r
243                 tween._onStart.fire();\r
244                 me.start();\r
245             },\r
246             \r
247             unRegister: function(tween, index){\r
248                 tween._onComplete.fire();\r
249                 index = index || getIndex(tween);\r
250                 if (index != -1) {\r
251                     queue.splice(index, 1);\r
252                 }\r
253 \r
254                 if (--tweenCount <= 0) {\r
255                     me.stop();\r
256                 }\r
257             },\r
258             \r
259             start: function(){\r
260                 if(thread === null){\r
261                     thread = setInterval(me.run, me.delay);\r
262                 }\r
263             },\r
264             \r
265             stop: function(tween){\r
266                 if(!tween){\r
267                     clearInterval(thread);\r
268                     for(var i = 0, len = queue.length; i < len; ++i){\r
269                         if(queue[0].isAnimated){\r
270                             me.unRegister(queue[0], 0);\r
271                         }\r
272                     }\r
273 \r
274                     queue = [];\r
275                     thread = null;\r
276                     tweenCount = 0;\r
277                 }else{\r
278                     me.unRegister(tween);\r
279                 }\r
280             },\r
281             \r
282             run: function(){\r
283                 var tf;\r
284                 Ext.each(queue, function(tween){\r
285                     if(tween && tween.isAnimated){\r
286                         tf = tween.totalFrames;\r
287                         if(tween.curFrame < tf || tf === null){\r
288                             ++tween.curFrame;\r
289                             if(tween.useSec){\r
290                                 correctFrame(tween);\r
291                             }\r
292                             tween._onTween.fire();\r
293                         }else{\r
294                             me.stop(tween);\r
295                         }\r
296                     }\r
297                 }, me);\r
298             }\r
299         });\r
300 \r
301         var getIndex = function(anim) {\r
302             var out = -1;\r
303             Ext.each(queue, function(item, idx){\r
304                 if(item == anim){\r
305                     out = idx;\r
306                     return false;\r
307                 }\r
308             });\r
309             return out;\r
310         };\r
311 \r
312 \r
313         var correctFrame = function(tween) {\r
314             var frames = tween.totalFrames,\r
315                 frame = tween.curFrame,\r
316                 duration = tween.duration,\r
317                 expected = (frame * duration * 1000 / frames),\r
318                 elapsed = (now() - tween.startTime),\r
319                 tweak = 0;\r
320 \r
321             if(elapsed < duration * 1000){\r
322                 tweak = Math.round((elapsed / expected - 1) * frame);\r
323             }else{\r
324                 tweak = frames - (frame + 1);\r
325             }\r
326             if(tweak > 0 && isFinite(tweak)){\r
327                 if(tween.curFrame + tweak >= frames){\r
328                     tweak = frames - (frame + 1);\r
329                 }\r
330                 tween.curFrame += tweak;\r
331             }\r
332         };\r
333     };\r
334 \r
335     EXTLIB.Bezier = new function() {\r
336 \r
337         this.getPosition = function(points, t) {\r
338             var n = points.length,\r
339                 tmp = [],\r
340                 c = 1 - t, \r
341                 i,\r
342                 j;\r
343 \r
344             for (i = 0; i < n; ++i) {\r
345                 tmp[i] = [points[i][0], points[i][1]];\r
346             }\r
347 \r
348             for (j = 1; j < n; ++j) {\r
349                 for (i = 0; i < n - j; ++i) {\r
350                     tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];\r
351                     tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];\r
352                 }\r
353             }\r
354 \r
355             return [ tmp[0][0], tmp[0][1] ];\r
356 \r
357         };\r
358     };\r
359 \r
360 \r
361     EXTLIB.Easing = {\r
362         easeNone: function (t, b, c, d) {\r
363             return c * t / d + b;\r
364         },\r
365 \r
366 \r
367         easeIn: function (t, b, c, d) {\r
368             return c * (t /= d) * t + b;\r
369         },\r
370 \r
371 \r
372         easeOut: function (t, b, c, d) {\r
373             return -c * (t /= d) * (t - 2) + b;\r
374         }\r
375     };\r
376 \r
377     (function() {\r
378         EXTLIB.Motion = function(el, attributes, duration, method) {\r
379             if (el) {\r
380                 EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);\r
381             }\r
382         };\r
383 \r
384         Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);\r
385 \r
386         var superclass = EXTLIB.Motion.superclass,\r
387             proto = EXTLIB.Motion.prototype,\r
388             pointsRe = /^points$/i;\r
389 \r
390         Ext.apply(EXTLIB.Motion.prototype, {\r
391             setAttr: function(attr, val, unit){\r
392                 var me = this,\r
393                     setAttr = superclass.setAttr;\r
394                     \r
395                 if (pointsRe.test(attr)) {\r
396                     unit = unit || 'px';\r
397                     setAttr.call(me, 'left', val[0], unit);\r
398                     setAttr.call(me, 'top', val[1], unit);\r
399                 } else {\r
400                     setAttr.call(me, attr, val, unit);\r
401                 }\r
402             },\r
403             \r
404             getAttr: function(attr){\r
405                 var me = this,\r
406                     getAttr = superclass.getAttr;\r
407                     \r
408                 return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);\r
409             },\r
410             \r
411             doMethod: function(attr, start, end){\r
412                 var me = this;\r
413                 \r
414                 return pointsRe.test(attr)\r
415                         ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)\r
416                         : superclass.doMethod.call(me, attr, start, end);\r
417             },\r
418             \r
419             setRunAttr: function(attr){\r
420                 if(pointsRe.test(attr)){\r
421                     \r
422                     var me = this,\r
423                         el = this.el,\r
424                         points = this.attributes.points,\r
425                         control = points.control || [],\r
426                         from = points.from,\r
427                         to = points.to,\r
428                         by = points.by,\r
429                         DOM = EXTLIB.Dom,\r
430                         start,\r
431                         i,\r
432                         end,\r
433                         len,\r
434                         ra;\r
435                   \r
436 \r
437                     if(control.length > 0 && !Ext.isArray(control[0])){\r
438                         control = [control];\r
439                     }else{\r
440                         /*\r
441                         var tmp = [];\r
442                         for (i = 0,len = control.length; i < len; ++i) {\r
443                             tmp[i] = control[i];\r
444                         }\r
445                         control = tmp;\r
446                         */\r
447                     }\r
448 \r
449                     Ext.fly(el, '_anim').position();\r
450                     DOM.setXY(el, isset(from) ? from : DOM.getXY(el));\r
451                     start = me.getAttr('points');\r
452 \r
453 \r
454                     if(isset(to)){\r
455                         end = translateValues.call(me, to, start);\r
456                         for (i = 0,len = control.length; i < len; ++i) {\r
457                             control[i] = translateValues.call(me, control[i], start);\r
458                         }\r
459                     } else if (isset(by)) {\r
460                         end = [start[0] + by[0], start[1] + by[1]];\r
461 \r
462                         for (i = 0,len = control.length; i < len; ++i) {\r
463                             control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];\r
464                         }\r
465                     }\r
466 \r
467                     ra = this.runAttrs[attr] = [start];\r
468                     if (control.length > 0) {\r
469                         ra = ra.concat(control);\r
470                     }\r
471 \r
472                     ra[ra.length] = end;\r
473                 }else{\r
474                     superclass.setRunAttr.call(this, attr);\r
475                 }\r
476             }\r
477         });\r
478 \r
479         var translateValues = function(val, start) {\r
480             var pageXY = EXTLIB.Dom.getXY(this.el);\r
481             return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];\r
482         };\r
483     })();\r
484 })();</pre>
485 </body>
486 </html>