Il rendering dell'HTML in un canvas WebGL ti consente di utilizzare sottoalberi DOM attivi come texture GPU dinamiche, applicare effetti shader al DOM attivo e integrare HTML interattivo in scene 3D.
Questa guida illustra come eseguire il rendering di HTML in un canvas WebGL. Scopri di più su HTML in Canvas nella panoramica dell'API.
Il rendering dell'HTML in un canvas WebGL richiede i seguenti passaggi:
- 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.
- Applica l'HTML come texture:
- Pre-allocare lo spazio di archiviazione delle texture della GPU.
- Carica l'istantanea DOM come texture.
- Sincronizza il DOM e i pixel.
Disegna un elemento HTML come texture WebGL
In WebGL, gli elementi HTML vengono caricati sulla GPU come texture 2D utilizzando texElementSubImage2D().
Pre-allocate texture storage
A differenza di un canvas 2D, che gestisce automaticamente la memoria di supporto, un contesto WebGL richiede una gestione esplicita della memoria.
Prima di caricare i pixel DOM, devi preallocare la memoria della GPU. In questo modo, il browser può eseguire aggiornamenti rapidi delle immagini secondarie senza attivare costose riallocazioni della memoria della GPU.
Pre-alloca il buffer con i parametri di dimensione selezionati e srcData impostato su null come segue:
// Only allocate texture backing once
if (!textureBufferAllocated) {
// Pre-allocate texture backing with pre-determined size.
gl.texImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* internalformat */ gl.RGBA8,
/* width */ myElementWidth,
/* height */ myElementHeight,
/* border */ 0,
/* format */ gl.RGBA,
/* type */ gl.UNSIGNED_BYTE,
/* srcData */ null
);
textureBufferAllocated = true;
}
Affinché la texture corrisponda alle dimensioni del layout naturale dell'elemento HTML, utilizza canvas.getElementImageDefaultSize() per recuperare le dimensioni predefinite in pixel della griglia del canvas:
const { width, height } = canvas.getElementImageDefaultSize(myElement);
// Pre-allocate texture backing. Only do this once, or whenever the element
// changes size.
gl.texImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* internalformat */ gl.RGBA8,
/* width */ Math.ceil(width),
/* height */ Math.ceil(height),
/* border */ 0,
/* format */ gl.RGBA,
/* type */ gl.UNSIGNED_BYTE,
/* srcData */ null
);
Carica l'istantanea DOM come texture
Il passaggio successivo consiste nel caricare l'elemento HTML nella texture all'interno del loop di rendering o del listener paint.
canvas.onpaint = () => {
// 1. Pre-allocate texture backing first
// ...
// 2. Upload HTML snapshot into the WebGL texture
gl.texElementSubImage2D(
/* target */ gl.TEXTURE_2D,
/* level */ 0,
/* xoffset */ 0,
/* yoffset */ 0,
/* element */ myElement // or an ElementImage from `captureElementImage()`
);
// ...
};
Sincronizza la geometria
A differenza dei contesti 2D, il browser non può dedurre automaticamente dove appare la texture sullo schermo in un contesto 3D. Devi allineare manualmente l'hit test DOM e i riquadri di delimitazione dell'accessibilità con la mesh 3D.
Per farlo, crea una DOMMatrix che mappa il riquadro del bordo dell'elemento alla posizione dei pixel del canvas visualizzato, quindi applicala utilizzando updateElementGeometry():
canvas.addEventListener("paint", () => {
// 1. Upload fresh DOM snapshot to GPU texture
gl.bindTexture(gl.TEXTURE_2D, myTexture);
gl.texElementSubImage2D(gl.TEXTURE_2D, 0, 0, 0, myElement);
// 2. Draw your 3D scene
draw3DScene();
// 3. Construct the CSS-pixel transform mapping the element's
// border box to its drawn position on the canvas as needed
// (for example: scale and translate)
const canvasTransform = new DOMMatrix();
// scale X
canvasTransform.a = canvas.clientWidth / myElement.offsetWidth;
// scale Y
canvasTransform.d = canvas.clientHeight / myElement.offsetHeight;
// translate X (CSS px)
canvasTransform.e = 50;
// translate Y (CSS px)
canvasTransform.f = 100;
// 4. Update DOM position, accessibility focus rings, and pointer hit-testing
canvas.updateElementGeometry(myElement, {
canvasTransform: canvasTransform,
});
});
Passaggi successivi
- Comprendere i concetti tecnici fondamentali alla base di HTML-in-Canvas.
- Scopri come eseguire il rendering di HTML in un contesto 2D.
- Scopri come eseguire il rendering del codice HTML in un canvas WebGPU.
- Scopri di più sulle strategie di riserva.
- Invia una segnalazione su GitHub per condividere il tuo feedback.
- Dai un'occhiata alla raccolta di demo HTML-in-Canvas della community.