| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>  <style type="text/css">    .highlight { display: block; background-color: #ddd; }  </style>  <script type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-fx-Anim'>/**</span> * This class manages animation for a specific {@link #target}. The animation allows * animation of various properties on the target, such as size, position, color and others. * * ## Starting Conditions * * The starting conditions for the animation are provided by the {@link #from} configuration. * Any/all of the properties in the {@link #from} configuration can be specified. If a particular * property is not defined, the starting value for that property will be read directly from the target. * * ## End Conditions * * The ending conditions for the animation are provided by the {@link #to} configuration. These mark * the final values once the animations has finished. The values in the {@link #from} can mirror * those in the {@link #to} configuration to provide a starting point. * * ## Other Options * *  - {@link #duration}: Specifies the time period of the animation. *  - {@link #easing}: Specifies the easing of the animation. *  - {@link #iterations}: Allows the animation to repeat a number of times. *  - {@link #alternate}: Used in conjunction with {@link #iterations}, reverses the direction every second iteration. * * ## Example Code * *     @example *     var myComponent = Ext.create('Ext.Component', { *         renderTo: document.body, *         width: 200, *         height: 200, *         style: 'border: 1px solid red;' *     }); * *     Ext.create('Ext.fx.Anim', { *         target: myComponent, *         duration: 1000, *         from: { *             width: 400 //starting width 400 *         }, *         to: { *             width: 300, //end width 300 *             height: 300 // end height 300 *         } *     }); */Ext.define('Ext.fx.Anim', {    /* Begin Definitions */    mixins: {        observable: 'Ext.util.Observable'    },    requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],    /* End Definitions */<span id='Ext-fx-Anim-property-isAnimation'>    /**</span>     * @property {Boolean} isAnimation     * `true` in this class to identify an object as an instantiated Anim, or subclass thereof.     */    isAnimation: true,<span id='Ext-fx-Anim-cfg-callback'>    /**</span>     * @cfg {Function} callback     * A function to be run after the animation has completed.     */<span id='Ext-fx-Anim-cfg-scope'>    /**</span>     * @cfg {Function} scope     * The scope that the {@link #callback} function will be called with     */<span id='Ext-fx-Anim-cfg-duration'>    /**</span>     * @cfg {Number} duration     * Time in milliseconds for a single animation to last. If the {@link #iterations} property is     * specified, then each animate will take the same duration for each iteration.     */    duration: 250,<span id='Ext-fx-Anim-cfg-delay'>    /**</span>     * @cfg {Number} delay     * Time to delay before starting the animation.     */    delay: 0,    /* @private used to track a delayed starting time */    delayStart: 0,<span id='Ext-fx-Anim-cfg-dynamic'>    /**</span>     * @cfg {Boolean} dynamic     * Currently only for Component Animation: Only set a component's outer element size bypassing layouts.     * Set to true to do full layouts for every frame of the animation.     */    dynamic: false,<span id='Ext-fx-Anim-cfg-easing'>    /**</span>     * @cfg {String} easing     * This describes how the intermediate values used during a transition will be calculated.     * It allows for a transition to change speed over its duration.     *     * - backIn     * - backOut     * - bounceIn     * - bounceOut     * - ease     * - easeIn     * - easeOut     * - easeInOut     * - elasticIn     * - elasticOut     * - cubic-bezier(x1, y1, x2, y2)     *     * Note that cubic-bezier will create a custom easing curve following the CSS3 [transition-timing-function][0]     * specification.  The four values specify points P1 and P2 of the curve as (x1, y1, x2, y2). All values must     * be in the range [0, 1] or the definition is invalid.     *     * [0]: http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag     */    easing: 'ease',<span id='Ext-fx-Anim-cfg-keyframes'>    /**</span>     * @cfg {Object} keyframes     * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'     * is considered '100%'. **Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using     * "from" or "to".**  A keyframe declaration without these keyframe selectors is invalid and will not be available for     * animation.  The keyframe declaration for a keyframe rule consists of properties and values. Properties that are unable to     * be animated are ignored in these rules, with the exception of 'easing' which can be changed at each keyframe. For example:     *     *     keyframes : {     *         '0%': {     *             left: 100     *         },     *         '40%': {     *             left: 150     *         },     *         '60%': {     *             left: 75     *         },     *         '100%': {     *             left: 100     *         }     *     }     */<span id='Ext-fx-Anim-property-damper'>    /**</span>     * @private     */    damper: 1,<span id='Ext-fx-Anim-property-bezierRE'>    /**</span>     * @private     */    bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,<span id='Ext-fx-Anim-cfg-reverse'>    /**</span>     * Run the animation from the end to the beginning     * Defaults to false.     * @cfg {Boolean} reverse     */    reverse: false,<span id='Ext-fx-Anim-property-running'>    /**</span>     * Flag to determine if the animation has started     * @property running     * @type Boolean     */    running: false,<span id='Ext-fx-Anim-property-paused'>    /**</span>     * Flag to determine if the animation is paused. Only set this to true if you need to     * keep the Anim instance around to be unpaused later; otherwise call {@link #end}.     * @property paused     * @type Boolean     */    paused: false,<span id='Ext-fx-Anim-cfg-iterations'>    /**</span>     * @cfg {Number} iterations     * Number of times to execute the animation.     */    iterations: 1,<span id='Ext-fx-Anim-cfg-alternate'>    /**</span>     * @cfg {Boolean} alternate     * Used in conjunction with iterations to reverse the animation each time an iteration completes.     */    alternate: false,<span id='Ext-fx-Anim-property-currentIteration'>    /**</span>     * Current iteration the animation is running.     * @property currentIteration     * @type Number     */    currentIteration: 0,<span id='Ext-fx-Anim-property-startTime'>    /**</span>     * Starting time of the animation.     * @property startTime     * @type Date     */    startTime: 0,<span id='Ext-fx-Anim-property-propHandlers'>    /**</span>     * Contains a cache of the interpolators to be used.     * @private     * @property propHandlers     * @type Object     */<span id='Ext-fx-Anim-cfg-target'>    /**</span>     * @cfg {String/Object} target     * The {@link Ext.fx.target.Target} to apply the animation to.  This should only be specified when creating an Ext.fx.Anim directly.     * The target does not need to be a {@link Ext.fx.target.Target} instance, it can be the underlying object. For example, you can     * pass a Component, Element or Sprite as the target and the Anim will create the appropriate {@link Ext.fx.target.Target} object     * automatically.     */<span id='Ext-fx-Anim-cfg-from'>    /**</span>     * @cfg {Object} from     * An object containing property/value pairs for the beginning of the animation.  If not specified, the current state of the     * Ext.fx.target will be used. For example:     *     *     from: {     *         opacity: 0,       // Transparent     *         color: '#ffffff', // White     *         left: 0     *     }     *     */<span id='Ext-fx-Anim-cfg-to'>    /**</span>     * @cfg {Object} to (required)     * An object containing property/value pairs for the end of the animation. For example:     *     *     to: {     *         opacity: 1,       // Opaque     *         color: '#00ff00', // Green     *         left: 500     *     }     *     */        // @private    frameCount: 0,    // @private    constructor: function(config) {        var me = this,            curve;                    config = config || {};        // If keyframes are passed, they really want an Animator instead.        if (config.keyframes) {            return new Ext.fx.Animator(config);        }        Ext.apply(me, config);        if (me.from === undefined) {            me.from = {};        }        me.propHandlers = {};        me.config = config;        me.target = Ext.fx.Manager.createTarget(me.target);        me.easingFn = Ext.fx.Easing[me.easing];        me.target.dynamic = me.dynamic;        // If not a pre-defined curve, try a cubic-bezier        if (!me.easingFn) {            me.easingFn = String(me.easing).match(me.bezierRE);            if (me.easingFn && me.easingFn.length == 5) {                curve = me.easingFn;                me.easingFn = Ext.fx.CubicBezier.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);            }        }        me.id = Ext.id(null, 'ext-anim-');        me.addEvents(<span id='Ext-fx-Anim-event-beforeanimate'>            /**</span>             * @event beforeanimate             * Fires before the animation starts. A handler can return false to cancel the animation.             * @param {Ext.fx.Anim} this             */            'beforeanimate',<span id='Ext-fx-Anim-event-afteranimate'>             /**</span>              * @event afteranimate              * Fires when the animation is complete.              * @param {Ext.fx.Anim} this              * @param {Date} startTime              */            'afteranimate',<span id='Ext-fx-Anim-event-lastframe'>             /**</span>              * @event lastframe              * Fires when the animation's last frame has been set.              * @param {Ext.fx.Anim} this              * @param {Date} startTime              */            'lastframe'        );        me.mixins.observable.constructor.call(me);        Ext.fx.Manager.addAnim(me);    },<span id='Ext-fx-Anim-method-setAttr'>    /**</span>     * @private     * Helper to the target     */    setAttr: function(attr, value) {        return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);    },<span id='Ext-fx-Anim-method-initAttrs'>    /**</span>     * @private     * Set up the initial currentAttrs hash.     */    initAttrs: function() {        var me = this,            from = me.from,            to = me.to,            initialFrom = me.initialFrom || {},            out = {},            start, end, propHandler, attr;        for (attr in to) {            if (to.hasOwnProperty(attr)) {                start = me.target.getAttr(attr, from[attr]);                end = to[attr];                // Use default (numeric) property handler                if (!Ext.fx.PropertyHandler[attr]) {                    if (Ext.isObject(end)) {                        propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;                    } else {                        propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;                    }                }                // Use custom handler                else {                    propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];                }                out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);            }        }        me.currentAttrs = out;    },<span id='Ext-fx-Anim-method-start'>    /**</span>     * @private     * Fires beforeanimate and sets the running flag.     */    start: function(startTime) {        var me = this,            delay = me.delay,            delayStart = me.delayStart,            delayDelta;                if (delay) {            if (!delayStart) {                me.delayStart = startTime;                return;            }            else {                delayDelta = startTime - delayStart;                if (delayDelta < delay) {                    return;                }                else {                    // Compensate for frame delay;                    startTime = new Date(delayStart.getTime() + delay);                }            }        }        if (me.fireEvent('beforeanimate', me) !== false) {            me.startTime = startTime;            if (!me.paused && !me.currentAttrs) {                me.initAttrs();            }            me.running = true;            me.frameCount = 0;        }    },<span id='Ext-fx-Anim-method-runAnim'>    /**</span>     * @private     * Calculate attribute value at the passed timestamp.     * @returns a hash of the new attributes.     */    runAnim: function(elapsedTime) {        var me = this,            attrs = me.currentAttrs,            duration = me.duration,            easingFn = me.easingFn,            propHandlers = me.propHandlers,            ret = {},            easing, values, attr, lastFrame;        if (elapsedTime >= duration) {            elapsedTime = duration;            lastFrame = true;        }        if (me.reverse) {            elapsedTime = duration - elapsedTime;        }        for (attr in attrs) {            if (attrs.hasOwnProperty(attr)) {                values = attrs[attr];                easing = lastFrame ? 1 : easingFn(elapsedTime / duration);                ret[attr] = propHandlers[attr].set(values, easing);            }        }        me.frameCount++;                    return ret;    },<span id='Ext-fx-Anim-method-lastFrame'>    /**</span>     * @private     * Perform lastFrame cleanup and handle iterations     * @returns a hash of the new attributes.     */    lastFrame: function() {        var me = this,            iter = me.iterations,            iterCount = me.currentIteration;        iterCount++;        if (iterCount < iter) {            if (me.alternate) {                me.reverse = !me.reverse;            }            me.startTime = new Date();            me.currentIteration = iterCount;            // Turn off paused for CSS3 Transitions            me.paused = false;        }        else {            me.currentIteration = 0;            me.end();            me.fireEvent('lastframe', me, me.startTime);        }    },    endWasCalled: 0,<span id='Ext-fx-Anim-method-end'>    /**</span>     * Fire afteranimate event and end the animation. Usually called automatically when the     * animation reaches its final frame, but can also be called manually to pre-emptively     * stop and destroy the running animation.     */    end: function() {        if (this.endWasCalled++) {            return;        }        var me = this;        me.startTime = 0;        me.paused = false;        me.running = false;        Ext.fx.Manager.removeAnim(me);        me.fireEvent('afteranimate', me, me.startTime);        Ext.callback(me.callback, me.scope, [me, me.startTime]);    },        isReady: function() {        return this.paused === false && this.running === false && this.iterations > 0;    },        isRunning: function() {        return this.paused === false && this.running === true && this.isAnimator !== true;    }});// Set flag to indicate that Fx is available. Class might not be available immediately.Ext.enableFx = true;</pre></body></html>
 |