Esegui il rendering dell'HTML in un canvas 2D

L'API HTML-in-Canvas consente di eseguire il rendering di sottoalberi DOM interattivi e accessibili direttamente in un contesto canvas 2D. Leggi la panoramica di HTML-in-Canvas per scoprire di più sull'API e sui suoi vantaggi.

Questa guida mostra come eseguire il rendering di HTML in un canvas 2D. Il rendering dell'HTML in un canvas 2D richiede i seguenti passaggi:

  1. Prepara la tela. Imposta in modo dichiarativo gli attributi corretti per far sapere al browser che deve eseguire il rendering del codice HTML in un canvas. Questa configurazione è identica nei contesti 2D, WebGL e WebGPU. Scopri come configurare il canvas e come dichiarare gli elementi HTML da disegnare in modo indipendente.
  2. Disegna l'immagine dell'elemento nel canvas.
  3. [Facoltativo] Sincronizza il DOM e i pixel.

Disegna elementi HTML in un canvas 2D

Una volta che il canvas è pronto e gli elementi sono contrassegnati come drawable, esegui il rendering nel contesto 2D utilizzando il metodo drawElementImage().

const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const childElement1 = document.getElementById("childElement1");
const childElement2 = document.getElementById("childElement2");

canvas.onpaint = () => {
  ctx.reset();
  // 1. Draw the primary element at coordinate (20, 20)
  ctx.drawElementImage(childElement1, 20, 20);
  // 2. Draw the secondary nested button at a custom offset
  ctx.drawElementImage(childElement2, 40, 90);
}

drawElementImage() supporta forme con 3, 5, 7 e 9 argomenti e accetta un parametro options facoltativo:

// 1. Basic position: (element, dx, dy, options?)
ctx.drawElementImage(targetElement, 100, 150);

// 2. Scaled / resized: (element, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 100, 150, 180, 60);

// 3. Cropped, default size: (element, sx, sy, swidth, sheight, dx, dy, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150);

// 4. Cropped and resized: (element, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, options?)
ctx.drawElementImage(targetElement, 0, 0, 90, 30, 100, 150, 180, 60);
Modulo di sovraccarico Parametri Effetto layout
Dimensioni predefinite (element, dx, dy) L'intero elemento alle dimensioni predefinite, con l'angolo in alto a sinistra in (dx, dy).
Riquadro Destinazione personalizzata (element, dx, dy, dwidth, dheight) Scala l'immagine dell'intero elemento in un'area visibile dw × dh sul canvas.
Ritagliato, dimensioni predefinite (element, sx, sy, swidth, sheight, dx, dy) Solo l'area swidth × sheight che inizia da (sx, sy), disegnata con le dimensioni predefinite dell'area (la stessa scala del modulo con dimensioni predefinite).
Sezione di origine nella destinazione (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) Ritaglia l'elemento di origine a partire da (sx, sy) con dimensioni swidth × sheight, quindi lo mappa alla destinazione (dx, dy, dwidth, dheight).

Sincronizza il DOM e i pixel

Poiché il rendering di <canvas> è imperativo, mentre il layout DOM e lo stile CSS sono reattivi, il browser ha bisogno di un meccanismo per mantenere sincronizzati i pixel del canvas visualizzati, le regioni di hit test interattive e gli alberi di accessibilità. Prima di imparare a sincronizzare il DOM e i pixel, assicurati di comprendere l'evento paint che viene attivato quando gli elementi DOM vengono aggiornati e devono essere ridisegnati.

Nei contesti canvas 2D, il browser sincronizza automaticamente le coordinate di layout dell'elemento, i limiti di accessibilità e l'hit test del puntatore con le coordinate del canvas disegnato.

Aggiorna manualmente la geometria degli elementi

In scenari avanzati, puoi disattivare la sincronizzazione automatica della geometria e controllare manualmente le trasformazioni spaziali. Passa { preserveElementGeometry: true } a drawElementImage() per impedire al browser di eseguire automaticamente l'override delle coordinate dell'hit test esistenti dell'elemento:

// 1. Draw the element without altering its existing hit-test bounds
ctx.drawElementImage(targetElement, elementX, 200, { preserveElementGeometry: true });

// 2. Construct a custom transform matrix as needed,
// assuming scaleX/scaleY = canvas grid pixels per CSS pixel,
// from your resize observer (see "Units and sizing").
const currentTransform = new DOMMatrix();
currentTransform.a = 1.5;          // scale X
currentTransform.e = x / scaleX;   // translate X: grid px → CSS px
currentTransform.f = y / scaleY;   // translate Y: grid px → CSS px

// 3. Explicitly apply the custom transform
canvas.updateElementGeometry(targetElement, { canvasTransform: currentTransform });
In 2D, drawElementImage() aggiorna automaticamente questa geometria. Questa demo mostra come la geometria non è sincronizzata quando è impostato { preserveElementGeometry: true }.

Passaggi successivi