You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							247 lines
						
					
					
						
							5.3 KiB
						
					
					
				
			
		
		
	
	
							247 lines
						
					
					
						
							5.3 KiB
						
					
					
				var util = require("../core/util"); | 
						|
 | 
						|
var _event = require("../core/event"); | 
						|
 | 
						|
var Dispatcher = _event.Dispatcher; | 
						|
 | 
						|
var requestAnimationFrame = require("./requestAnimationFrame"); | 
						|
 | 
						|
var Animator = require("./Animator"); | 
						|
 | 
						|
/** | 
						|
 * 动画主类, 调度和管理所有动画控制器 | 
						|
 * | 
						|
 * @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, | 
						|
 | 
						|
  /** | 
						|
   * 添加 clip | 
						|
   * @param {module:zrender/animation/Clip} clip | 
						|
   */ | 
						|
  addClip: function (clip) { | 
						|
    this._clips.push(clip); | 
						|
  }, | 
						|
 | 
						|
  /** | 
						|
   * 添加 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]); | 
						|
    } | 
						|
  }, | 
						|
 | 
						|
  /** | 
						|
   * 删除动画片段 | 
						|
   * @param {module:zrender/animation/Clip} clip | 
						|
   */ | 
						|
  removeClip: function (clip) { | 
						|
    var idx = util.indexOf(this._clips, clip); | 
						|
 | 
						|
    if (idx >= 0) { | 
						|
      this._clips.splice(idx, 1); | 
						|
    } | 
						|
  }, | 
						|
 | 
						|
  /** | 
						|
   * 删除动画片段 | 
						|
   * @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; |