var dataUtil = require("../utils/data_structure_util"); var classUtil = require("../utils/class_util"); var _event_util = require("../utils/event_util"); var Dispatcher = _event_util.Dispatcher; var requestAnimationFrame = require("./request_animation_frame"); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } /** * @singleton * @class qrenderer.animation.GlobalAnimationMgr * * Animation manager, global singleton, controls all the animation processes. * Each QRenderer instance has a GlobalAnimationMgr instance. GlobalAnimationMgr * is designed to manage all the elements that are animating. * * 动画管理器,全局单例,控制和调度所有动画过程。每个 qrenderer 实例中会持有一个 * GlobalAnimationMgr 实例。GlobalAnimationMgr 会管理 qrenderer 实例中的所有 * 正在进行动画的元素。 * * @author pissang(https://github.com/pissang) * @docauthor 大漠穷秋 <damoqiongqiu@126.com> */ // TODO Additive animation // http://iosoteric.com/additive-animations-animatewithduration-in-ios-8/ // https://developer.apple.com/videos/wwdc2014/#236 var GlobalAnimationMgr = /*#__PURE__*/ function () { /** * @method constructor GlobalAnimationMgr * @param {Object} [options] */ function GlobalAnimationMgr(options) { _classCallCheck(this, GlobalAnimationMgr); options = options || {}; this._animatableMap = new Map(); this._running = false; this._timestamp; this._pausedTime; //ms this._pauseStart; this._paused = false; Dispatcher.call(this); } /** * @method addAnimatable * @param {*} animatable */ _createClass(GlobalAnimationMgr, [{ key: "addAnimatable", value: function addAnimatable(animatable) { this._animatableMap.set(animatable.id, animatable); } /** * @method removeAnimatable * @param {*} animatable */ }, { key: "removeAnimatable", value: function removeAnimatable(animatable) { this._animatableMap["delete"](animatable.id); } /** * @private * @method _update */ }, { key: "_update", value: function _update() { var _this = this; var time = new Date().getTime() - this._pausedTime; var delta = time - this._timestamp; this._animatableMap.forEach(function (animatable, index, map) { var ap = animatable.animationProcessList[0]; if (!ap) { _this.removeAnimatable(animatable); return; } ap.nextFrame(time, delta); }); this._timestamp = time; this.trigger('frame', delta); } /** * @private * @method _startLoop * Execute recursively with requestAnimationFrame. * The 60fps is a recommended standard of W3C, the nextFrame function * here will be called every 16ms. * If the _update() method here can't finish a round of animations in 16ms, there will be significant lags. * * 这里开始利用 requestAnimationFrame 递归执行, * 按照 W3C 的推荐标准 60fps,这里的 nextFrame 函数大约每隔 16ms 被调用一次, * 如果这里的 _update() 不能在 6ms 的时间内完成一轮动画,就会出现明显的卡顿。 * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame */ }, { key: "_startLoop", value: function _startLoop() { var self = this; this._running = true; function nextFrame() { if (self._running) { requestAnimationFrame(nextFrame); !self._paused && self._update(); } } requestAnimationFrame(nextFrame); } /** * @method start * Start animating. * * * 启动动画。 */ }, { key: "start", value: function start() { this._timestamp = new Date().getTime(); this._pausedTime = 0; this._startLoop(); } /** * @method pause * Pause the animations. * * * 暂停动画。 */ }, { key: "pause", value: function pause() { if (!this._paused) { this._pauseStart = new Date().getTime(); this._paused = true; } } /** * @method resume * Resume the animations. * * * 恢复动画。 */ }, { key: "resume", value: function resume() { if (this._paused) { this._pausedTime += new Date().getTime() - this._pauseStart; this._paused = false; } } /** * @method clear * Clear the animations. * * * 清除动画。 */ }, { key: "clear", value: function clear() { this._animatableMap.forEach(function (animatable, index) { animatable.stopAnimation(); }); this._running = false; this._animatableMap = new Map(); } }]); return GlobalAnimationMgr; }(); classUtil.mixin(GlobalAnimationMgr, Dispatcher); var _default = GlobalAnimationMgr; module.exports = _default;