OffscreenCanvas - 善用網路工作處理工具,可加快畫布作業速度

Tim Dresser

畫布是很熱門的做法 在畫面上繪製各種圖像,再做為 WebGL 的進入點。 可用來繪製形狀、圖片、執行動畫,甚至是顯示和處理影片內容。 經常用於在含有多媒體內容的網路應用程式中,提供美觀的使用者體驗。 線上遊戲。

此元件可編寫指令碼,也就是說,畫布上繪製的內容可透過程式建立。 例如 JavaScript這種畫布提供絕佳彈性。

同時,在現代網站上,指令碼執行頻率是 使用者回應問題的來源。 畫布邏輯和算繪作業是在與使用者互動相同的執行緒上進行, 動畫中涉及的運算 (有時會耗用大量資源) 可能會影響應用程式的 以及使用者感知的效能

幸運的是 OffscreenCanvas 回應該威脅

瀏覽器支援

  • 69
  • 79
  • 105
  • 16.4

資料來源

先前,畫布繪圖功能是與 <canvas> 元素綁定的。 也就是直接依附於 DOM顧名思義, 將 DOM 和 Canvas API 移至螢幕外,藉此分離該 DOM 和 Canvas API。

多虧有這種分離,「OffscreenCanvas」的算繪已經從 DOM 完全卸離, 因此速度比一般畫布稍有改善,因為網頁既沒有同步處理 兩者之間

另外,雖然在網路工作處理程序中,即使沒有 可使用 DOM。這可支援各種有趣的用途。

在工作站中使用 OffscreenCanvas

工作站 是網路的執行緒,可讓您在背景執行工作。

將部分指令碼移至工作站,可讓應用程式有更多執行重要使用者的工作空間 處理主執行緒的工作如果沒有 OffscreenCanvas,就無法在 worker 中使用 Canvas API 沒有可用的 DOM。

OffscreenCanvas 不會依賴 DOM,所以可以用。以下範例使用 OffscreenCanvas 計算 worker 中的漸層顏色:

// file: worker.js
function getGradientColor(percent) {
  const canvas = new OffscreenCanvas(100, 1);
  const ctx = canvas.getContext('2d');
  const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  gradient.addColorStop(0, 'red');
  gradient.addColorStop(1, 'blue');
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, ctx.canvas.width, 1);
  const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
  const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
  return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}

getGradientColor(40);  // rgba(152, 0, 104, 255 )

解除封鎖主執行緒

將繁重計算作業移交給工作站 掌握主要執行緒上的重要資源使用 transferControlToOffscreen 方法將一般畫布鏡像到 OffscreenCanvas 執行個體。套用的作業對象 系統會自動在來源畫布上顯示 OffscreenCanvas。

const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);

在下列範例中,系統會在色彩主題變更時進行大量計算, 甚至還要花幾毫秒的時間你可以選擇在主執行緒上執行動畫 或在 worker 中在主要執行緒的情況下,您無法在重型執行緒的情況下與按鈕互動 工作正在執行中,但執行緒遭到封鎖。若是 worker,則不會影響 UI 回應速度。

示範

其他做法也是如此:忙碌的主執行緒不會影響在上面的動畫 工作站您可以使用這項功能避免影像卡頓,並確保動畫流暢播放 即使主要執行緒流量仍不受影響,如以下範例所示

示範

如果是一般畫布,當主要執行緒人為過勞時,動畫就會停止; 以工作站為基礎的 OffscreenCanvas 則流暢播放。

由於 OffscreenCanvas API 通常與一般的 Canvas Element 相容,您可以 ,進一步改良產品,以及市面上一些主要的圖像庫。

例如,只要指定 以下為轉譯器建構函式中的畫布選項:

const canvasEl = document.querySelector('canvas');
const canvas =
  'OffscreenCanvas' in window
    ? canvasEl.transferControlToOffscreen()
    : canvasEl;
canvas.style = {width: 0, height: 0};
const renderer = new THREE.WebGLRenderer({canvas: canvas});

這裡的重點在於 Three.js 預期的畫布具有 style.widthstyle.height 屬性。 與 DOM 完全卸離的 OffscreenCanvas 沒有它,所以您需要自行提供 一種是直接練習 或是建立將這些值與 畫布尺寸

以下顯示如何在工作站中執行基本的 Three.js 動畫:

示範

請注意,部分 DOM 相關 API 無法在 worker 中隨時使用, 如要使用紋理等更進階的 Three.js 功能,您可能需要更多替代方案。 如要瞭解如何開始實驗這些程式,請參閱 觀看 2017 年 Google I/O 大會的影片

如要大量使用畫布的圖形功能,不妨考慮使用 OffscreenCanvas 影響應用程式效能讓工作人員能夠使用畫布轉譯背景內容 也更妥善地運用多核心系統。

其他資源