Chrome 157 的 HTML-in-Canvas:2D、WebGL 和 WebGPU 中的互動式 DOM

發布日期:2026 年 10 月 26 日

來源試用成功後,Chrome 157 正式推出 HTML-in-Canvas API 的穩定版本。HTML-in-Canvas API 彌補了 DOM 的互動式無障礙世界,與 <canvas> 的高效能像素級控制之間的差距。這個 API 結合了兩者的優點,既有豐富的瀏覽器功能,也有 GPU 加速的畫布圖形。

HTML-in-Canvas API 影片總覽。

Canvas 與 DOM 的兩難

以往,建立視覺效果要求較高的網頁應用程式時,必須在標準 HTML 元素和原始畫布內容之間做出選擇。

科技 優勢 限制
<canvas> 可透過 GPU 存取權進行低階像素控制,驅動 2D 和 3D 圖形管道、自訂著色器和螢幕外工作站。高效能轉譯,適合資料密集的繁重 UI。 沒有內建的網頁平台功能,例如文字選取、複製及貼上、按一下滑鼠右鍵動作和文字換行。不透明像素網格預設不支援螢幕閱讀器、網頁內搜尋、自動翻譯或自動填入功能,因此需要備用導入方式。
HTML 內建表單控制項、回應式字體排版和 CSS 樣式,可直接使用 Semantic UI。與瀏覽器深度整合,支援螢幕閱讀器、網頁內搜尋和開發人員工具。 控制複雜 UI 效能的能力有限。視覺效果僅限標準 CSS 和 SVG,不得直接操作像素或使用著色器。

HTML-in-Canvas 推出前

在這個 API 推出前,如果您建構了大量使用畫布的 UI,就必須在兩種方法之間做出選擇,而這兩種方法各有缺點:

  1. 直接將文字算繪為畫布像素 (fillText()):應用程式會以原始像素的形式,強制繪製文字和 UI 控制項。這種做法有以下缺點:
    • 無障礙功能故障:除非手動建構並同步處理隱藏的備用 DOM,否則螢幕閱讀器和輔助工具無法讀取畫布像素。
    • 無法使用瀏覽器功能:使用者無法使用「在網頁中尋找」功能 (Ctrl/Cmd+F) 搜尋、自然地複製及貼上文字、觸發內容選單,或使用瀏覽器翻譯和拼字檢查功能。
    • 複雜的字體排版引擎:如要支援國際化,必須綁定大型 JavaScript 版面配置引擎。
  2. 在畫布上浮動 HTML 疊加層:例如,使用程式庫,在 JavaScript 中計算定界框和矩陣轉換,將標準 HTML 元素置於畫布上。這種做法的缺點包括:
    • 同步延遲和畫面撕裂:在 3D 模式下捲動、縮放或移動鏡頭時,疊加層 DOM 元素可能會因影格時間差異,而相對於畫布像素產生偏移或抖動。
    • 裁剪和 Z 軸排序限制:HTML 疊加層一律位於整個畫布緩衝區的頂端。在 3D 場景中嵌入 HTML (例如在 3D 物件後方、玻璃材質內或鏡面反射中),需要複雜的 iframe 轉圖片解決方法。
    • 效能負擔:為了讓疊加層與畫布對齊,您必須在 JavaScript 中重新計算每個疊加層的轉換,並在每個影格中寫入 style.transform。接著,瀏覽器會剖析每個字串,並重新計算元素樣式,然後才能算繪影格,因此主執行緒工作會隨著您新增的疊加層而增加。在 2D 情境中,drawElementImage() 會為您更新元素的位置。在 WebGL 和 WebGPU 中,您會將計算出的轉換以矩陣形式傳遞至 updateElementGeometry()。無論採用哪種方式,瀏覽器都不會剖析 CSS 或重新計算樣式。

HTML-in-Canvas 的主要優點

HTML-in-Canvas 則可消除這些缺點。將 HTML 放入 <canvas> 元素中,內容仍可互動,且所有瀏覽器整合功能都會自動運作。

在 <canvas> 內轉譯的 HTML 內容,與 <canvas> 外的 HTML 具有相同功能:

  • 文字版面配置和格式:支援文字版面配置和格式,包括套用 CSS 樣式的多行或雙向文字。
  • 表單控制項:提供豐富的表單控制項,以及多種 CSS 和著色器自訂選項。
  • 選取、複製、貼上文字,以及按一下滑鼠右鍵:使用者可以醒目顯示 3D 場景中的文字,或觸發內容選單。
  • 無障礙功能:在畫布中算繪的 HTML 內容會公開給螢幕閱讀器的無障礙樹狀結構。
  • 整合瀏覽器功能:翻譯、自動填入和網頁內搜尋等瀏覽器功能可立即使用。使用者可以翻譯或搜尋 WebGL 和 WebGPU 紋理中的文字。
  • 擴充功能整合:瀏覽器擴充功能會處理內容。舉例來說,文字替換擴充功能會自動更新 3D 網格上顯示的文字。
  • 開發人員工具整合:直接在 Chrome 開發人員工具中,檢查及調整畫布 UI 元素的 CSS 樣式。
  • 可索引性和 AI 代理:網路檢索器和 AI 代理可為轉譯成 2D 和 3D 場景的 DOM 內容建立索引。
  • 媒體編輯和匯出:將包含即時 DOM 元素的完整畫布合成內容,直接匯出為圖片 (toDataURL()、toBlob()) 或影片串流 (captureStream())。
示範比較直接在畫布中算繪文字和 HTML-in-Canvas 的功能整合。在 HTML-in-Canvas 窗格中,您可以選取及翻譯內容,並直接使用自動填入等瀏覽器功能。在標準畫布窗格中,內容會使用 fillText 方法直接算繪到畫布中,且不具互動性。

主要用途

HTML-in-Canvas 可在多個領域發揮作用:

  • 大型畫布應用程式:重量級網頁應用程式可直接在畫布工作區中轉譯 UI 元件,提升無障礙程度並縮減套件大小。
  • 3D 場景和遊戲:沉浸式 WebXR 體驗和遊戲可將互動式 DOM 元素 (例如遊戲內終端機或可讀取的 3D 書籍) 直接置於場景中。
  • 媒體編輯和匯出:結合豐富 HTML 字體排版和著色器效果的創意工具,可直接將複合場景匯出為圖片或影片串流。
  • 表現力豐富的使用者介面:您可以將 HTML 內容當做原始像素進行操作,建構著色器驅動的視覺效果。

HTML-in-Canvas 快速入門導覽課程

如要在畫布中算繪 HTML,請按照下列步驟操作:

  1. 準備畫布。以宣告方式設定正確的屬性,讓瀏覽器知道應將 HTML 轉譯為畫布。這項設定在 2D、WebGL 和 WebGPU 環境中都相同。瞭解如何設定畫布,以及如何宣告要獨立繪製的 HTML 元素。

    <!-- Prepare your canvas by setting the `content` attribute -->
    <canvas id="canvas" width="600" height="400" content="drawable">
      <!-- Mark child as `drawable` to render to canvas -->
      <div id="myElement" drawable>
        <!-- Your HTML here -->
      </div>
    </canvas>
    
  2. 將元素圖片繪製到畫布上。具體導入方式取決於您是在 2D、WebGL 還是 WebGPU 環境中算繪 HTML。

    const ctx = canvas.getContext("2d");
    // Draw HTML element into canvas in 2D
    ctx.drawElementImage(myElement, myElementX, myElementY);
    
  3. 選用:同步處理 DOM 和像素。幾何圖形同步處理也取決於您使用的情境。在 2D 模式下,瀏覽器預設會自動處理,但在 3D 情境下,您需要建構轉換並傳遞至 updateElementGeometry 方法。

    // In 3D, construct a transform as needed, for example:
    const transform = new DOMMatrix().translate(x, y);
    // Synchronize the element's DOM and pixels
    canvas.updateElementGeometry(myElement, { canvasTransform: transform });
    

框架和生態系統支援

主要的 WebGL 和 3D 圖形程式庫支援 HTML-in-Canvas:

  • Three.js:提供使用 THREE.HTMLTexture 的實驗支援。

    const material = new THREE.MeshBasicMaterial();
    material.map = new THREE.HTMLTexture(uiElement);
    const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material);
    scene.add(mesh);
    
  • PlayCanvas:支援使用 setSource() 串流 HTML 紋理。

    canvas.addEventListener('paint', () => {
      htmlTexture.setSource(htmlElement);
    }, { once: true });
    
  • Babylon.js:透過 BABYLON.HtmlTexture 提供內建繫結。

    const htmlTexture = new BABYLON.HtmlTexture("htmlTexture", uiElement, scene);
    material.diffuseTexture = htmlTexture;
    
  • PixiJS:在 v8.19.0 版本中內建支援 HTMLSource。

    import { HTMLSource } from 'pixi.js/html-source';
    const sprite = Sprite.from(new HTMLSource({ resource: form, autoUpdate: true }));
    app.stage.addChild(sprite);
    
  • CanvasUI:專為 HTML-in-Canvas 設計的開放原始碼元件庫。

如要進一步瞭解實作細節,請參閱各架構的說明文件。

功能偵測和備用策略

為確保跨瀏覽器相容性,請先確認 API 支援情形,再執行程式碼:

export function supportsHtmlInCanvas() {
  if (typeof document === "undefined") return false;
  const canvas = document.createElement("canvas");
  canvas.setAttribute("content", "drawable");
  return canvas.content === "drawable";
}

如果無法使用 API,可以改用其他 UI、浮動 HTML 疊加層,或其中一個可用的程式庫 (例如 three-html-render、html2canvas 或 dom-to-image)。

後續步驟