| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 | var util = require("../core/util");var _event = require("../core/event");var Dispatcher = _event.Dispatcher;var requestAnimationFrame = require("./requestAnimationFrame");var Animator = require("./Animator");/** * Animation main class, dispatch and manage all animation controllers * * @module zrender/animation/Animation * @author pissang(https://github.com/pissang) */// TODO Additive animation// http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/// https://developer.apple.com/videos/wwdc2014/#236/** * @typedef {Object} IZRenderStage * @property {Function} update *//** * @alias module:zrender/animation/Animation * @constructor * @param {Object} [options] * @param {Function} [options.onframe] * @param {IZRenderStage} [options.stage] * @example *     var animation = new Animation(); *     var obj = { *         x: 100, *         y: 100 *     }; *     animation.animate(node.position) *         .when(1000, { *             x: 500, *             y: 500 *         }) *         .when(2000, { *             x: 100, *             y: 100 *         }) *         .start('spline'); */var Animation = function (options) {  options = options || {};  this.stage = options.stage || {};  this.onframe = options.onframe || function () {}; // private properties  this._clips = [];  this._running = false;  this._time;  this._pausedTime;  this._pauseStart;  this._paused = false;  Dispatcher.call(this);};Animation.prototype = {  constructor: Animation,  /**   * Add clip   * @param {module:zrender/animation/Clip} clip   */  addClip: function (clip) {    this._clips.push(clip);  },  /**   * Add animator   * @param {module:zrender/animation/Animator} animator   */  addAnimator: function (animator) {    animator.animation = this;    var clips = animator.getClips();    for (var i = 0; i < clips.length; i++) {      this.addClip(clips[i]);    }  },  /**   * Delete animation clip   * @param {module:zrender/animation/Clip} clip   */  removeClip: function (clip) {    var idx = util.indexOf(this._clips, clip);    if (idx >= 0) {      this._clips.splice(idx, 1);    }  },  /**   * Delete animation clip   * @param {module:zrender/animation/Animator} animator   */  removeAnimator: function (animator) {    var clips = animator.getClips();    for (var i = 0; i < clips.length; i++) {      this.removeClip(clips[i]);    }    animator.animation = null;  },  _update: function () {    var time = new Date().getTime() - this._pausedTime;    var delta = time - this._time;    var clips = this._clips;    var len = clips.length;    var deferredEvents = [];    var deferredClips = [];    for (var i = 0; i < len; i++) {      var clip = clips[i];      var e = clip.step(time, delta); // Throw out the events need to be called after      // stage.update, like destroy      if (e) {        deferredEvents.push(e);        deferredClips.push(clip);      }    } // Remove the finished clip    for (var i = 0; i < len;) {      if (clips[i]._needsRemove) {        clips[i] = clips[len - 1];        clips.pop();        len--;      } else {        i++;      }    }    len = deferredEvents.length;    for (var i = 0; i < len; i++) {      deferredClips[i].fire(deferredEvents[i]);    }    this._time = time;    this.onframe(delta); // 'frame' should be triggered before stage, because upper application    // depends on the sequence (e.g., echarts-stream and finish    // event judge)    this.trigger('frame', delta);    if (this.stage.update) {      this.stage.update();    }  },  _startLoop: function () {    var self = this;    this._running = true;    function step() {      if (self._running) {        requestAnimationFrame(step);        !self._paused && self._update();      }    }    requestAnimationFrame(step);  },  /**   * Start animation.   */  start: function () {    this._time = new Date().getTime();    this._pausedTime = 0;    this._startLoop();  },  /**   * Stop animation.   */  stop: function () {    this._running = false;  },  /**   * Pause animation.   */  pause: function () {    if (!this._paused) {      this._pauseStart = new Date().getTime();      this._paused = true;    }  },  /**   * Resume animation.   */  resume: function () {    if (this._paused) {      this._pausedTime += new Date().getTime() - this._pauseStart;      this._paused = false;    }  },  /**   * Clear animation.   */  clear: function () {    this._clips = [];  },  /**   * Whether animation finished.   */  isFinished: function () {    return !this._clips.length;  },  /**   * Creat animator for a target, whose props can be animated.   *   * @param  {Object} target   * @param  {Object} options   * @param  {boolean} [options.loop=false] Whether loop animation.   * @param  {Function} [options.getter=null] Get value from target.   * @param  {Function} [options.setter=null] Set value to target.   * @return {module:zrender/animation/Animation~Animator}   */  // TODO Gap  animate: function (target, options) {    options = options || {};    var animator = new Animator(target, options.loop, options.getter, options.setter);    this.addAnimator(animator);    return animator;  }};util.mixin(Animation, Dispatcher);var _default = Animation;module.exports = _default;
 |