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;