Animation.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. var util = require("../core/util");
  2. var _event = require("../core/event");
  3. var Dispatcher = _event.Dispatcher;
  4. var requestAnimationFrame = require("./requestAnimationFrame");
  5. var Animator = require("./Animator");
  6. /**
  7. * 动画主类, 调度和管理所有动画控制器
  8. *
  9. * @module zrender/animation/Animation
  10. * @author pissang(https://github.com/pissang)
  11. */
  12. // TODO Additive animation
  13. // http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/
  14. // https://developer.apple.com/videos/wwdc2014/#236
  15. /**
  16. * @typedef {Object} IZRenderStage
  17. * @property {Function} update
  18. */
  19. /**
  20. * @alias module:zrender/animation/Animation
  21. * @constructor
  22. * @param {Object} [options]
  23. * @param {Function} [options.onframe]
  24. * @param {IZRenderStage} [options.stage]
  25. * @example
  26. * var animation = new Animation();
  27. * var obj = {
  28. * x: 100,
  29. * y: 100
  30. * };
  31. * animation.animate(node.position)
  32. * .when(1000, {
  33. * x: 500,
  34. * y: 500
  35. * })
  36. * .when(2000, {
  37. * x: 100,
  38. * y: 100
  39. * })
  40. * .start('spline');
  41. */
  42. var Animation = function (options) {
  43. options = options || {};
  44. this.stage = options.stage || {};
  45. this.onframe = options.onframe || function () {}; // private properties
  46. this._clips = [];
  47. this._running = false;
  48. this._time;
  49. this._pausedTime;
  50. this._pauseStart;
  51. this._paused = false;
  52. Dispatcher.call(this);
  53. };
  54. Animation.prototype = {
  55. constructor: Animation,
  56. /**
  57. * 添加 clip
  58. * @param {module:zrender/animation/Clip} clip
  59. */
  60. addClip: function (clip) {
  61. this._clips.push(clip);
  62. },
  63. /**
  64. * 添加 animator
  65. * @param {module:zrender/animation/Animator} animator
  66. */
  67. addAnimator: function (animator) {
  68. animator.animation = this;
  69. var clips = animator.getClips();
  70. for (var i = 0; i < clips.length; i++) {
  71. this.addClip(clips[i]);
  72. }
  73. },
  74. /**
  75. * 删除动画片段
  76. * @param {module:zrender/animation/Clip} clip
  77. */
  78. removeClip: function (clip) {
  79. var idx = util.indexOf(this._clips, clip);
  80. if (idx >= 0) {
  81. this._clips.splice(idx, 1);
  82. }
  83. },
  84. /**
  85. * 删除动画片段
  86. * @param {module:zrender/animation/Animator} animator
  87. */
  88. removeAnimator: function (animator) {
  89. var clips = animator.getClips();
  90. for (var i = 0; i < clips.length; i++) {
  91. this.removeClip(clips[i]);
  92. }
  93. animator.animation = null;
  94. },
  95. _update: function () {
  96. var time = new Date().getTime() - this._pausedTime;
  97. var delta = time - this._time;
  98. var clips = this._clips;
  99. var len = clips.length;
  100. var deferredEvents = [];
  101. var deferredClips = [];
  102. for (var i = 0; i < len; i++) {
  103. var clip = clips[i];
  104. var e = clip.step(time, delta); // Throw out the events need to be called after
  105. // stage.update, like destroy
  106. if (e) {
  107. deferredEvents.push(e);
  108. deferredClips.push(clip);
  109. }
  110. } // Remove the finished clip
  111. for (var i = 0; i < len;) {
  112. if (clips[i]._needsRemove) {
  113. clips[i] = clips[len - 1];
  114. clips.pop();
  115. len--;
  116. } else {
  117. i++;
  118. }
  119. }
  120. len = deferredEvents.length;
  121. for (var i = 0; i < len; i++) {
  122. deferredClips[i].fire(deferredEvents[i]);
  123. }
  124. this._time = time;
  125. this.onframe(delta);
  126. this.trigger('frame', delta);
  127. if (this.stage.update) {
  128. this.stage.update();
  129. }
  130. },
  131. _startLoop: function () {
  132. var self = this;
  133. this._running = true;
  134. function step() {
  135. if (self._running) {
  136. requestAnimationFrame(step);
  137. !self._paused && self._update();
  138. }
  139. }
  140. requestAnimationFrame(step);
  141. },
  142. /**
  143. * 开始运行动画
  144. */
  145. start: function () {
  146. this._time = new Date().getTime();
  147. this._pausedTime = 0;
  148. this._startLoop();
  149. },
  150. /**
  151. * 停止运行动画
  152. */
  153. stop: function () {
  154. this._running = false;
  155. },
  156. /**
  157. * Pause
  158. */
  159. pause: function () {
  160. if (!this._paused) {
  161. this._pauseStart = new Date().getTime();
  162. this._paused = true;
  163. }
  164. },
  165. /**
  166. * Resume
  167. */
  168. resume: function () {
  169. if (this._paused) {
  170. this._pausedTime += new Date().getTime() - this._pauseStart;
  171. this._paused = false;
  172. }
  173. },
  174. /**
  175. * 清除所有动画片段
  176. */
  177. clear: function () {
  178. this._clips = [];
  179. },
  180. /**
  181. * 对一个目标创建一个animator对象,可以指定目标中的属性使用动画
  182. * @param {Object} target
  183. * @param {Object} options
  184. * @param {boolean} [options.loop=false] 是否循环播放动画
  185. * @param {Function} [options.getter=null]
  186. * 如果指定getter函数,会通过getter函数取属性值
  187. * @param {Function} [options.setter=null]
  188. * 如果指定setter函数,会通过setter函数设置属性值
  189. * @return {module:zrender/animation/Animation~Animator}
  190. */
  191. // TODO Gap
  192. animate: function (target, options) {
  193. options = options || {};
  194. var animator = new Animator(target, options.loop, options.getter, options.setter);
  195. this.addAnimator(animator);
  196. return animator;
  197. }
  198. };
  199. util.mixin(Animation, Dispatcher);
  200. var _default = Animation;
  201. module.exports = _default;