(function(){ var EXTLIB = Ext.lib, noNegatives = /width|height|opacity|padding/i, offsetAttribute = /^((width|height)|(top|left))$/, defaultUnit = /width|height|top$|bottom$|left$|right$/i, offsetUnit = /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i, isset = function(v){ return typeof v !== 'undefined'; }, now = function(){ return new Date(); }; EXTLIB.Anim = { motion : function(el, args, duration, easing, cb, scope) { return this.run(el, args, duration, easing, cb, scope, Ext.lib.Motion); }, run : function(el, args, duration, easing, cb, scope, type) { type = type || Ext.lib.AnimBase; if (typeof easing == "string") { easing = Ext.lib.Easing[easing]; } var anim = new type(el, args, duration, easing); anim.animateX(function() { if(Ext.isFunction(cb)){ cb.call(scope); } }); return anim; } }; EXTLIB.AnimBase = function(el, attributes, duration, method) { if (el) { this.init(el, attributes, duration, method); } }; EXTLIB.AnimBase.prototype = { doMethod: function(attr, start, end) { var me = this; return me.method(me.curFrame, start, end - start, me.totalFrames); }, setAttr: function(attr, val, unit) { if (noNegatives.test(attr) && val < 0) { val = 0; } Ext.fly(this.el, '_anim').setStyle(attr, val + unit); }, getAttr: function(attr) { var el = Ext.fly(this.el), val = el.getStyle(attr), a = offsetAttribute.exec(attr) || [] if (val !== 'auto' && !offsetUnit.test(val)) { return parseFloat(val); } return (!!(a[2]) || (el.getStyle('position') == 'absolute' && !!(a[3]))) ? el.dom['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)] : 0; }, getDefaultUnit: function(attr) { return defaultUnit.test(attr) ? 'px' : ''; }, animateX : function(callback, scope) { var me = this, f = function() { me.onComplete.removeListener(f); if (Ext.isFunction(callback)) { callback.call(scope || me, me); } }; me.onComplete.addListener(f, me); me.animate(); }, setRunAttr: function(attr) { var me = this, a = this.attributes[attr], to = a.to, by = a.by, from = a.from, unit = a.unit, ra = (this.runAttrs[attr] = {}), end; if (!isset(to) && !isset(by)){ return false; } var start = isset(from) ? from : me.getAttr(attr); if (isset(to)) { end = to; }else if(isset(by)) { if (Ext.isArray(start)){ end = []; Ext.each(start, function(v, i){ end[i] = v + by[i]; }); }else{ end = start + by; } } Ext.apply(ra, { start: start, end: end, unit: isset(unit) ? unit : me.getDefaultUnit(attr) }); }, init: function(el, attributes, duration, method) { var me = this, actualFrames = 0, mgr = EXTLIB.AnimMgr; Ext.apply(me, { isAnimated: false, startTime: null, el: Ext.getDom(el), attributes: attributes || {}, duration: duration || 1, method: method || EXTLIB.Easing.easeNone, useSec: true, curFrame: 0, totalFrames: mgr.fps, runAttrs: {}, animate: function(){ var me = this, d = me.duration; if(me.isAnimated){ return false; } me.curFrame = 0; me.totalFrames = me.useSec ? Math.ceil(mgr.fps * d) : d; mgr.registerElement(me); }, stop: function(finish){ var me = this; if(finish){ me.curFrame = me.totalFrames; me._onTween.fire(); } mgr.stop(me); } }); var onStart = function(){ var me = this, attr; me.onStart.fire(); me.runAttrs = {}; for(attr in this.attributes){ this.setRunAttr(attr); } me.isAnimated = true; me.startTime = now(); actualFrames = 0; }; var onTween = function(){ var me = this; me.onTween.fire({ duration: now() - me.startTime, curFrame: me.curFrame }); var ra = me.runAttrs; for (var attr in ra) { this.setAttr(attr, me.doMethod(attr, ra[attr].start, ra[attr].end), ra[attr].unit); } ++actualFrames; }; var onComplete = function() { var me = this, actual = (now() - me.startTime) / 1000, data = { duration: actual, frames: actualFrames, fps: actualFrames / actual }; me.isAnimated = false; actualFrames = 0; me.onComplete.fire(data); }; me.onStart = new Ext.util.Event(me); me.onTween = new Ext.util.Event(me); me.onComplete = new Ext.util.Event(me); (me._onStart = new Ext.util.Event(me)).addListener(onStart); (me._onTween = new Ext.util.Event(me)).addListener(onTween); (me._onComplete = new Ext.util.Event(me)).addListener(onComplete); } }; Ext.lib.AnimMgr = new function() { var me = this, thread = null, queue = [], tweenCount = 0; Ext.apply(me, { fps: 1000, delay: 1, registerElement: function(tween){ queue.push(tween); ++tweenCount; tween._onStart.fire(); me.start(); }, unRegister: function(tween, index){ tween._onComplete.fire(); index = index || getIndex(tween); if (index != -1) { queue.splice(index, 1); } if (--tweenCount <= 0) { me.stop(); } }, start: function(){ if(thread === null){ thread = setInterval(me.run, me.delay); } }, stop: function(tween){ if(!tween){ clearInterval(thread); for(var i = 0, len = queue.length; i < len; ++i){ if(queue[0].isAnimated){ me.unRegister(queue[0], 0); } } queue = []; thread = null; tweenCount = 0; }else{ me.unRegister(tween); } }, run: function(){ var tf; Ext.each(queue, function(tween){ if(tween && tween.isAnimated){ tf = tween.totalFrames; if(tween.curFrame < tf || tf === null){ ++tween.curFrame; if(tween.useSec){ correctFrame(tween); } tween._onTween.fire(); }else{ me.stop(tween); } } }, me); } }); var getIndex = function(anim) { var out = -1; Ext.each(queue, function(item, idx){ if(item == anim){ out = idx; return false; } }); return out; }; var correctFrame = function(tween) { var frames = tween.totalFrames, frame = tween.curFrame, duration = tween.duration, expected = (frame * duration * 1000 / frames), elapsed = (now() - tween.startTime), tweak = 0; if(elapsed < duration * 1000){ tweak = Math.round((elapsed / expected - 1) * frame); }else{ tweak = frames - (frame + 1); } if(tweak > 0 && isFinite(tweak)){ if(tween.curFrame + tweak >= frames){ tweak = frames - (frame + 1); } tween.curFrame += tweak; } }; }; EXTLIB.Bezier = new function() { this.getPosition = function(points, t) { var n = points.length, tmp = [], c = 1 - t, i, j; for (i = 0; i < n; ++i) { tmp[i] = [points[i][0], points[i][1]]; } for (j = 1; j < n; ++j) { for (i = 0; i < n - j; ++i) { tmp[i][0] = c * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0]; tmp[i][1] = c * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1]; } } return [ tmp[0][0], tmp[0][1] ]; }; }; EXTLIB.Easing = { easeNone: function (t, b, c, d) { return c * t / d + b; }, easeIn: function (t, b, c, d) { return c * (t /= d) * t + b; }, easeOut: function (t, b, c, d) { return -c * (t /= d) * (t - 2) + b; } }; (function() { EXTLIB.Motion = function(el, attributes, duration, method) { if (el) { EXTLIB.Motion.superclass.constructor.call(this, el, attributes, duration, method); } }; Ext.extend(EXTLIB.Motion, Ext.lib.AnimBase); var superclass = EXTLIB.Motion.superclass, proto = EXTLIB.Motion.prototype, pointsRe = /^points$/i; Ext.apply(EXTLIB.Motion.prototype, { setAttr: function(attr, val, unit){ var me = this, setAttr = superclass.setAttr; if (pointsRe.test(attr)) { unit = unit || 'px'; setAttr.call(me, 'left', val[0], unit); setAttr.call(me, 'top', val[1], unit); } else { setAttr.call(me, attr, val, unit); } }, getAttr: function(attr){ var me = this, getAttr = superclass.getAttr; return pointsRe.test(attr) ? [getAttr.call(me, 'left'), getAttr.call(me, 'top')] : getAttr.call(me, attr); }, doMethod: function(attr, start, end){ var me = this; return pointsRe.test(attr) ? EXTLIB.Bezier.getPosition(me.runAttrs[attr], me.method(me.curFrame, 0, 100, me.totalFrames) / 100) : superclass.doMethod.call(me, attr, start, end); }, setRunAttr: function(attr){ if(pointsRe.test(attr)){ var me = this, el = this.el, points = this.attributes.points, control = points.control || [], from = points.from, to = points.to, by = points.by, DOM = EXTLIB.Dom, start, i, end, len, ra; if(control.length > 0 && !Ext.isArray(control[0])){ control = [control]; }else{ /* var tmp = []; for (i = 0,len = control.length; i < len; ++i) { tmp[i] = control[i]; } control = tmp; */ } Ext.fly(el, '_anim').position(); DOM.setXY(el, isset(from) ? from : DOM.getXY(el)); start = me.getAttr('points'); if(isset(to)){ end = translateValues.call(me, to, start); for (i = 0,len = control.length; i < len; ++i) { control[i] = translateValues.call(me, control[i], start); } } else if (isset(by)) { end = [start[0] + by[0], start[1] + by[1]]; for (i = 0,len = control.length; i < len; ++i) { control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ]; } } ra = this.runAttrs[attr] = [start]; if (control.length > 0) { ra = ra.concat(control); } ra[ra.length] = end; }else{ superclass.setRunAttr.call(this, attr); } } }); var translateValues = function(val, start) { var pageXY = EXTLIB.Dom.getXY(this.el); return [val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1]]; }; })(); })();