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 |
瀏覽器相容性
載入中…