2021SC@SDUSC
今天来看一下动画过程中的另一个组件:全局图像管理器GlobalAnimationMgr
动画管理器,全局单例,控制和调度所有动画过程。每个 qrenderer 实例中会持有一个GlobalAnimationMgr 实例。GlobalAnimationMgr 会管理 qrenderer 实例中的所有正在进行动画的元素。
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);
}_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);
}
这里没什么好说的,就是单纯的将一些基础的参数进行了导入和定义,为后面的运行提供基础。
{
key: "_startLoop",
value: function _startLoop() {
var self = this;
this._running = true;
function nextFrame() {
if (self._running) {
requestAnimationFrame(nextFrame);
!self._paused && self._update();
}
}
requestAnimationFrame(nextFrame);
}
这里开始利用 requestAnimationFrame 递归执行,按照 W3C 的推荐标准 60fps,这里的 nextFrame 函数大约每隔 16ms 被调用一次,如果这里的 _update() 不能在 6ms 的时间内完成一轮动画,就会出现明显的卡顿。
只要您准备好在屏幕上更新动画,就应该调用此方法。这将要求在浏览器执行下一次重绘之前调用您的动画函数。回调的次数通常为每秒 60 次,但通常与 W3C 建议的大多数 Web 浏览器中的显示刷新率相匹配。requestAnimationFrame()
在后台选项卡或隐藏
<iframe>s 中运行时,大多数浏览器会暂停调用,以提高性能和电池寿命。
回调方法传递一个参数 DOMHighResTimeStamp,它指示当前时间(基于自时间以来的毫秒数)。当多个回调队列requestAnimationFrame()
开始在单个帧中触发时,每个回调都会收到相同的时间戳,即使在计算每个前一个回调的工作负载期间已经过去了(在下面的代码示例中,我们只在时间戳更改时对帧进行动画处理,即在第一次回调)。此时间戳是一个十进制数,以毫秒为单位,但最小精度为 1 毫秒(1000 微秒)。
callback
当需要为下一次重绘更新动画时调用的函数。回调函数传递一个参数,
DOMHighResTimeStamp类似于由 返回的参数performance.now() ,指示requestAnimationFrame()
开始执行回调函数的时间点 。
返回值:
一个long
整数值,请求 id,唯一标识回调列表中的条目。这是一个非零值,但您不能对其值做出任何其他假设。您可以将此值传递window.cancelAnimationFrame() 给以取消刷新回调请求。
{
key: "clear",
value: function clear() {
this._animatableMap.forEach(function (animatable, index) {
animatable.stopAnimation();
});
this._running = false;
this._animatableMap = new Map();
}
{
key: "clear",
value: function clear() {
this._animatableMap.forEach(function (animatable, index) {
animatable.stopAnimation();
});
this._running = false;
this._animatableMap = new Map();
}
{
key: "pause",
value: function pause() {
if (!this._paused) {
this._pauseStart = new Date().getTime();
this._paused = true;
}
}
{
key: "start",
value: function start() {
this._timestamp = new Date().getTime();
this._pausedTime = 0;
this._startLoop();
}
以上就是里面的清除,恢复,暂停和启动动画,就是利用cancelAnimationFrame来实现的。