DedicatedWorkerGlobalScope: requestAnimationFrame() 方法
注意:此功能仅在 专用 Web Worker 中可用。
DedicatedWorkerGlobalScope 接口的 requestAnimationFrame() 方法用于告知浏览器您希望请求一个动画帧,并在下一次重绘前调用一个用户提供的回调函数。
回调函数的调用频率通常与显示器的刷新率相匹配。最常见的刷新率是 60 Hz(每秒 60 个周期/帧),但 75 Hz、120 Hz 和 144 Hz 也被广泛使用。在大多数浏览器中,当运行在后台标签页或隐藏的 <iframe> 中时,requestAnimationFrame() 调用会被暂停,以提高性能和电池寿命。
调用 requestAnimationFrame() 方法只会安排一次对回调函数的调用。如果您想动画下一帧,您的回调函数必须再次调用 requestAnimationFrame()。
警告: 请务必始终使用第一个参数(或获取当前时间的其他方法)来计算动画在每一帧中将推进多少——否则,动画在刷新率较高的屏幕上会运行得更快。有关实现方法,请参见下方的示例。
调用 requestAnimationFrame() 方法需要当前 worker 拥有一个关联的 window。这意味着当前 worker 必须由 window 或一个同样拥有关联 window 的专用 worker 创建。
语法
requestAnimationFrame(callback)
参数
回调-
当需要更新动画以准备下一次重绘时要调用的函数。这个回调函数会接收一个单一的参数
时间戳-
一个
DOMHighResTimeStamp,指示前一帧渲染的结束时间(基于自 time origin 以来的毫秒数)。时间戳是一个十进制数,单位是毫秒,但最小精度为 1 毫秒。时间戳值也类似于在回调函数开始时调用performance.now(),但它永远不会是相同的值。当
requestAnimationFrame()排队的多个回调在同一帧中开始触发时,每个回调都会收到相同的时间戳,尽管在计算每个前置回调的工作负载期间已经过去了时间。
返回值
一个 long 整数值,即请求 ID,它唯一标识了回调列表中的条目。这是一个非零值,但您不能对此做任何其他假设。您可以将此值传递给 cancelAnimationFrame() 来取消刷新回调请求,取消操作必须在同一个 worker 中进行。
异常
NotSupportedErrorDOMException-
如果当前 worker 不支持该方法,则会抛出此异常。
示例
这是一个完整的示例,展示了如何在具有 OffscreenCanvas 的专用 worker 中使用 requestAnimationFrame()。
HTML 应包含
<canvas width="100" height="100"></canvas>
它应该链接到以下 JavaScript
const worker = new Worker("worker.js");
// Transfer canvas control to the worker
const offscreenCanvas = document
.querySelector("canvas")
.transferControlToOffscreen();
// Start the animation
worker.postMessage(
{
type: "start",
canvas: offscreenCanvas,
},
[offscreenCanvas],
);
// Stop the animation after 5 seconds
setTimeout(() => {
worker.postMessage({
type: "stop",
});
}, 5000);
worker.js
let ctx;
let pos = 0;
let animationId;
let isRunning = false;
let lastTime = 0;
function draw(currentTime) {
if (!isRunning) return;
// Calculate delta time for smooth animation
if (lastTime === 0) lastTime = currentTime;
const deltaTime = (currentTime - lastTime) / 1000;
lastTime = currentTime;
// Clear and draw the moving rectangle
ctx.clearRect(0, 0, 100, 100);
ctx.fillRect(pos, 0, 10, 10);
pos += 50 * deltaTime; // Move 50 pixels per second
// Loop the animation
if (pos > 100) pos = -10;
animationId = self.requestAnimationFrame(draw);
}
self.addEventListener("message", (e) => {
if (e.data.type === "start") {
const transferredCanvas = e.data.canvas;
ctx = transferredCanvas.getContext("2d");
isRunning = true;
lastTime = 0;
animationId = self.requestAnimationFrame(draw);
}
if (e.data.type === "stop") {
isRunning = false;
if (animationId) {
self.cancelAnimationFrame(animationId);
}
}
});
在主线程中,我们首先使用 HTMLCanvasElement.transferControlToOffscreen() 将 <canvas> 元素的控制权转移给一个 OffscreenCanvas,并向 worker 发送一条 "start" 消息,以启动其工作,并附带 offscreen canvas。
在 worker 文件 (worker.js) 中,我们处理动画逻辑。当收到 "start" 消息时,worker 开始动画,使矩形从左向右移动。收到 "stop" 消息时,它将停止动画。
最后,主线程可以在延迟后向 worker 发送 "stop" 消息以停止动画,从而在停止前允许动画可见。
规范
| 规范 |
|---|
| HTML # dom-animationframeprovider-requestanimationframe |
浏览器兼容性
加载中…