3 * Copyright(c) 2006-2010 Ext JS, Inc.
5 * http://www.extjs.com/license
9 noNegatives = /width|height|opacity|padding/i,
10 offsetAttribute = /^((width|height)|(top|left))$/,
11 defaultUnit = /width|height|top$|bottom$|left$|right$/i,
12 offsetUnit = /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i,
14 return typeof v !== 'undefined';
21 motion : function(el, args, duration, easing, cb, scope) {
22 return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion);
25 run : function(el, args, duration, easing, cb, scope, type) {
26 type = type || Ext.lib.AnimBase;
27 if (typeof easing == "string") {
28 easing = Ext.lib.Easing[easing];
30 var anim = new type(el, args, duration, easing);
31 anim.animateX(function() {
32 if(Ext.isFunction(cb)){
40 EXTLIB.AnimBase = function(el, attributes, duration, method) {
42 this.init(el, attributes, duration, method);
46 EXTLIB.AnimBase.prototype = {
47 doMethod: function(attr, start, end) {
49 return me.method(me.curFrame, start, end - start, me.totalFrames);
53 setAttr: function(attr, val, unit) {
54 if (noNegatives.test(attr) && val < 0) {
57 Ext.fly(this.el, '_anim').setStyle(attr, val + unit);
61 getAttr: function(attr) {
62 var el = Ext.fly(this.el),
63 val = el.getStyle(attr),
64 a = offsetAttribute.exec(attr) || [];
66 if (val !== 'auto' && !offsetUnit.test(val)) {
67 return parseFloat(val);
70 return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0;
74 getDefaultUnit: function(attr) {
75 return defaultUnit.test(attr) ? 'px' : '';
78 animateX : function(callback, scope) {
81 me.onComplete.removeListener(f);
82 if (Ext.isFunction(callback)) {
83 callback.call(scope || me, me);
86 me.onComplete.addListener(f, me);
91 setRunAttr: function(attr) {
93 a = this.attributes[attr],
98 ra = (this.runAttrs[attr] = {}),
101 if (!isset(to) && !isset(by)){
105 var start = isset(from) ? from : me.getAttr(attr);
108 }else if(isset(by)) {
109 if (Ext.isArray(start)){
111 for(var i=0,len=start.length; i<len; i++) {
112 end[i] = start[i] + by[i];
122 unit: isset(unit) ? unit : me.getDefaultUnit(attr)
127 init: function(el, attributes, duration, method) {
130 mgr = EXTLIB.AnimMgr;
136 attributes: attributes || {},
137 duration: duration || 1,
138 method: method || EXTLIB.Easing.easeNone,
141 totalFrames: mgr.fps,
152 me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d;
153 mgr.registerElement(me);
156 stop: function(finish){
160 me.curFrame = me.totalFrames;
167 var onStart = function(){
173 for(attr in this.attributes){
174 this.setRunAttr(attr);
177 me.isAnimated = true;
178 me.startTime = now();
183 var onTween = function(){
187 duration: now() - me.startTime,
188 curFrame: me.curFrame
191 var ra = me.runAttrs;
192 for (var attr in ra) {
193 this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit);
199 var onComplete = function() {
201 actual = (now() - me.startTime) / 1000,
204 frames: actualFrames,
205 fps: actualFrames / actual
208 me.isAnimated = false;
210 me.onComplete.fire(data);
213 me.onStart = new Ext.util.Event(me);
214 me.onTween = new Ext.util.Event(me);
215 me.onComplete = new Ext.util.Event(me);
216 (me._onStart = new Ext.util.Event(me)).addListener(onStart);
217 (me._onTween = new Ext.util.Event(me)).addListener(onTween);
218 (me._onComplete = new Ext.util.Event(me)).addListener(onComplete);
223 Ext.lib.AnimMgr = new function() {
233 registerElement: function(tween){
236 tween._onStart.fire();
240 unRegister: function(tween, index){
241 tween._onComplete.fire();
242 index = index || getIndex(tween);
244 queue.splice(index, 1);
247 if (--tweenCount <= 0) {
254 thread = setInterval(me.run, me.delay);
258 stop: function(tween){
260 clearInterval(thread);
261 for(var i = 0, len = queue.length; i < len; ++i){
262 if(queue[0].isAnimated){
263 me.unRegister(queue[0], 0);
271 me.unRegister(tween);
276 var tf, i, len, tween;
277 for(i = 0, len = queue.length; i<len; i++) {
279 if(tween && tween.isAnimated){
280 tf = tween.totalFrames;
281 if(tween.curFrame < tf || tf === null){
286 tween._onTween.fire();
295 var getIndex = function(anim) {
297 for(i = 0, len = queue.length; i<len; i++) {
298 if(queue[i] === anim) {
305 var correctFrame = function(tween) {
306 var frames = tween.totalFrames,
307 frame = tween.curFrame,
308 duration = tween.duration,
309 expected = (frame * duration * 1000 / frames),
310 elapsed = (now() - tween.startTime),
313 if(elapsed < duration * 1000){
314 tweak = Math.round((elapsed / expected - 1) * frame);
316 tweak = frames - (frame + 1);
318 if(tweak > 0 && isFinite(tweak)){
319 if(tween.curFrame + tweak >= frames){
320 tweak = frames - (frame + 1);
322 tween.curFrame += tweak;
327 EXTLIB.Bezier = new function() {
329 this.getPosition = function(points, t) {
330 var n = points.length,
336 for (i = 0; i < n; ++i) {
337 tmp[i] = [points[i][0], points[i][1]];
340 for (j = 1; j < n; ++j) {
341 for (i = 0; i < n - j; ++i) {
342 tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
343 tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
347 return [ tmp[0][0], tmp[0][1] ];
354 easeNone: function (t, b, c, d) {
355 return c * t / d + b;
359 easeIn: function (t, b, c, d) {
360 return c * (t /= d) * t + b;
364 easeOut: function (t, b, c, d) {
365 return -c * (t /= d) * (t - 2) + b;
370 EXTLIB.Motion = function(el, attributes, duration, method) {
372 EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method);
376 Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase);
378 var superclass = EXTLIB.Motion.superclass,
379 proto = EXTLIB.Motion.prototype,
380 pointsRe = /^points$/i;
382 Ext.apply(EXTLIB.Motion.prototype, {
383 setAttr: function(attr, val, unit){
385 setAttr = superclass.setAttr;
387 if (pointsRe.test(attr)) {
389 setAttr.call(me, 'left', val[0], unit);
390 setAttr.call(me, 'top', val[1], unit);
392 setAttr.call(me, attr, val, unit);
396 getAttr: function(attr){
398 getAttr = superclass.getAttr;
400 return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr);
403 doMethod: function(attr, start, end){
406 return pointsRe.test(attr)
407 ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100)
408 : superclass.doMethod.call(me, attr, start, end);
411 setRunAttr: function(attr){
412 if(pointsRe.test(attr)){
416 points = this.attributes.points,
417 control = points.control || [],
429 if(control.length > 0 && !Ext.isArray(control[0])){
434 for (i = 0,len = control.length; i < len; ++i) {
441 Ext.fly(el, '_anim').position();
442 DOM.setXY(el, isset(from) ? from : DOM.getXY(el));
443 start = me.getAttr('points');
447 end = translateValues.call(me, to, start);
448 for (i = 0,len = control.length; i < len; ++i) {
449 control[i] = translateValues.call(me, control[i], start);
451 } else if (isset(by)) {
452 end = [start[0] + by[0], start[1] + by[1]];
454 for (i = 0,len = control.length; i < len; ++i) {
455 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
459 ra = this.runAttrs[attr] = [start];
460 if (control.length > 0) {
461 ra = ra.concat(control);
466 superclass.setRunAttr.call(this, attr);
471 var translateValues = function(val, start) {
472 var pageXY = EXTLIB.Dom.getXY(this.el);
473 return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]];