123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- <!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-Animator'>/**
- </span> * @class Ext.fx.Animator
- *
- * This class is used to run keyframe based animations, which follows the CSS3 based animation structure.
- * Keyframe animations differ from typical from/to animations in that they offer the ability to specify values
- * at various points throughout the animation.
- *
- * ## Using Keyframes
- *
- * The {@link #keyframes} option is the most important part of specifying an animation when using this
- * class. A key frame is a point in a particular animation. We represent this as a percentage of the
- * total animation duration. At each key frame, we can specify the target values at that time. Note that
- * you *must* specify the values at 0% and 100%, the start and ending values. There is also a {@link #keyframe}
- * event that fires after each key frame is reached.
- *
- * ## Example
- *
- * In the example below, we modify the values of the element at each fifth throughout the animation.
- *
- * @example
- * Ext.create('Ext.fx.Animator', {
- * target: Ext.getBody().createChild({
- * style: {
- * width: '100px',
- * height: '100px',
- * 'background-color': 'red'
- * }
- * }),
- * duration: 10000, // 10 seconds
- * keyframes: {
- * 0: {
- * opacity: 1,
- * backgroundColor: 'FF0000'
- * },
- * 20: {
- * x: 30,
- * opacity: 0.5
- * },
- * 40: {
- * x: 130,
- * backgroundColor: '0000FF'
- * },
- * 60: {
- * y: 80,
- * opacity: 0.3
- * },
- * 80: {
- * width: 200,
- * y: 200
- * },
- * 100: {
- * opacity: 1,
- * backgroundColor: '00FF00'
- * }
- * }
- * });
- */
- Ext.define('Ext.fx.Animator', {
- /* Begin Definitions */
- mixins: {
- observable: 'Ext.util.Observable'
- },
- requires: ['Ext.fx.Manager'],
- /* End Definitions */
- <span id='Ext-fx-Animator-property-isAnimator'> /**
- </span> * @property {Boolean} isAnimator
- * `true` in this class to identify an object as an instantiated Animator, or subclass thereof.
- */
- isAnimator: true,
- <span id='Ext-fx-Animator-cfg-duration'> /**
- </span> * @cfg {Number} duration
- * Time in milliseconds for the animation to last. Defaults to 250.
- */
- duration: 250,
- <span id='Ext-fx-Animator-cfg-delay'> /**
- </span> * @cfg {Number} delay
- * Time to delay before starting the animation. Defaults to 0.
- */
- delay: 0,
- /* private used to track a delayed starting time */
- delayStart: 0,
- <span id='Ext-fx-Animator-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. Defaults to false.
- */
- dynamic: false,
- <span id='Ext-fx-Animator-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-Animator-property-running'> /**
- </span> * Flag to determine if the animation has started
- * @property running
- * @type Boolean
- */
- running: false,
- <span id='Ext-fx-Animator-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-Animator-property-damper'> /**
- </span> * @private
- */
- damper: 1,
- <span id='Ext-fx-Animator-cfg-iterations'> /**
- </span> * @cfg {Number} iterations
- * Number of times to execute the animation. Defaults to 1.
- */
- iterations: 1,
- <span id='Ext-fx-Animator-property-currentIteration'> /**
- </span> * Current iteration the animation is running.
- * @property currentIteration
- * @type Number
- */
- currentIteration: 0,
- <span id='Ext-fx-Animator-property-keyframeStep'> /**
- </span> * Current keyframe step of the animation.
- * @property keyframeStep
- * @type Number
- */
- keyframeStep: 0,
- <span id='Ext-fx-Animator-property-animKeyFramesRE'> /**
- </span> * @private
- */
- animKeyFramesRE: /^(from|to|\d+%?)$/,
- <span id='Ext-fx-Animator-cfg-target'> /**
- </span> * @cfg {Ext.fx.target.Target} target
- * The Ext.fx.target to apply the animation to. If not specified during initialization, this can be passed to the applyAnimator
- * method to apply the same animation to many targets.
- */
- <span id='Ext-fx-Animator-cfg-keyframes'> /**
- </span> * @cfg {Object} keyframes
- * Animation keyframes follow the CSS3 Animation configuration pattern. 'from' is always considered '0%' and 'to'
- * is considered '100%'.<b>Every keyframe declaration must have a keyframe rule for 0% and 100%, possibly defined using
- * "from" or "to"</b>. 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:
- <pre><code>
- keyframes : {
- '0%': {
- left: 100
- },
- '40%': {
- left: 150
- },
- '60%': {
- left: 75
- },
- '100%': {
- left: 100
- }
- }
- </code></pre>
- */
- constructor: function(config) {
- var me = this;
- config = Ext.apply(me, config || {});
- me.config = config;
- me.id = Ext.id(null, 'ext-animator-');
- me.addEvents(
- <span id='Ext-fx-Animator-event-beforeanimate'> /**
- </span> * @event beforeanimate
- * Fires before the animation starts. A handler can return false to cancel the animation.
- * @param {Ext.fx.Animator} this
- */
- 'beforeanimate',
- <span id='Ext-fx-Animator-event-keyframe'> /**
- </span> * @event keyframe
- * Fires at each keyframe.
- * @param {Ext.fx.Animator} this
- * @param {Number} keyframe step number
- */
- 'keyframe',
- <span id='Ext-fx-Animator-event-afteranimate'> /**
- </span> * @event afteranimate
- * Fires when the animation is complete.
- * @param {Ext.fx.Animator} this
- * @param {Date} startTime
- */
- 'afteranimate'
- );
- me.mixins.observable.constructor.call(me, config);
- me.timeline = [];
- me.createTimeline(me.keyframes);
- if (me.target) {
- me.applyAnimator(me.target);
- Ext.fx.Manager.addAnim(me);
- }
- },
- <span id='Ext-fx-Animator-method-sorter'> /**
- </span> * @private
- */
- sorter: function (a, b) {
- return a.pct - b.pct;
- },
- <span id='Ext-fx-Animator-method-createTimeline'> /**
- </span> * @private
- * Takes the given keyframe configuration object and converts it into an ordered array with the passed attributes per keyframe
- * or applying the 'to' configuration to all keyframes. Also calculates the proper animation duration per keyframe.
- */
- createTimeline: function(keyframes) {
- var me = this,
- attrs = [],
- to = me.to || {},
- duration = me.duration,
- prevMs, ms, i, ln, pct, anim, nextAnim, attr;
- for (pct in keyframes) {
- if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
- attr = {attrs: Ext.apply(keyframes[pct], to)};
- // CSS3 spec allow for from/to to be specified.
- if (pct == "from") {
- pct = 0;
- }
- else if (pct == "to") {
- pct = 100;
- }
- // convert % values into integers
- attr.pct = parseInt(pct, 10);
- attrs.push(attr);
- }
- }
- // Sort by pct property
- Ext.Array.sort(attrs, me.sorter);
- // Only an end
- //if (attrs[0].pct) {
- // attrs.unshift({pct: 0, attrs: element.attrs});
- //}
- ln = attrs.length;
- for (i = 0; i < ln; i++) {
- prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
- ms = duration * (attrs[i].pct / 100);
- me.timeline.push({
- duration: ms - prevMs,
- attrs: attrs[i].attrs
- });
- }
- },
- <span id='Ext-fx-Animator-property-applyAnimator'> /**
- </span> * Applies animation to the Ext.fx.target
- * @private
- * @param target
- * @type String/Object
- */
- applyAnimator: function(target) {
- var me = this,
- anims = [],
- timeline = me.timeline,
- reverse = me.reverse,
- ln = timeline.length,
- anim, easing, damper, initial, attrs, lastAttrs, i;
- if (me.fireEvent('beforeanimate', me) !== false) {
- for (i = 0; i < ln; i++) {
- anim = timeline[i];
- attrs = anim.attrs;
- easing = attrs.easing || me.easing;
- damper = attrs.damper || me.damper;
- delete attrs.easing;
- delete attrs.damper;
- anim = new Ext.fx.Anim({
- target: target,
- easing: easing,
- damper: damper,
- duration: anim.duration,
- paused: true,
- to: attrs
- });
- anims.push(anim);
- }
- me.animations = anims;
- me.target = anim.target;
- for (i = 0; i < ln - 1; i++) {
- anim = anims[i];
- anim.nextAnim = anims[i + 1];
- anim.on('afteranimate', function() {
- this.nextAnim.paused = false;
- });
- anim.on('afteranimate', function() {
- this.fireEvent('keyframe', this, ++this.keyframeStep);
- }, me);
- }
- anims[ln - 1].on('afteranimate', function() {
- this.lastFrame();
- }, me);
- }
- },
- <span id='Ext-fx-Animator-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;
- me.running = true;
- me.animations[me.keyframeStep].paused = false;
- }
- },
- <span id='Ext-fx-Animator-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) {
- me.startTime = new Date();
- me.currentIteration = iterCount;
- me.keyframeStep = 0;
- me.applyAnimator(me.target);
- me.animations[me.keyframeStep].paused = false;
- }
- else {
- me.currentIteration = 0;
- me.end();
- }
- },
- <span id='Ext-fx-Animator-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() {
- var me = this;
- me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);
- },
-
- isReady: function() {
- return this.paused === false && this.running === false && this.iterations > 0;
- },
-
- isRunning: function() {
- // Explicitly return false, we don't want to be run continuously by the manager
- return false;
- }
- });</pre>
- </body>
- </html>
|