Le rendu HTML dans un canevas WebGL vous permet d'utiliser des sous-arborescences DOM actives comme textures GPU dynamiques, d'appliquer des effets de nuanceur au DOM actif et d'intégrer du code HTML interactif dans des scènes 3D.
Ce guide explique comment afficher du code HTML dans un canevas WebGL. Pour en savoir plus sur le HTML dans Canvas, consultez la présentation de l'API.
Pour afficher du code HTML dans un canevas WebGL, procédez comme suit :
- Préparez votre toile. Définissez de manière déclarative les attributs appropriés pour indiquer au navigateur qu'il doit afficher du code HTML dans un canevas. Cette configuration est identique pour les contextes 2D, WebGL et WebGPU. Découvrez comment configurer votre canevas et comment déclarer des éléments HTML à dessiner indépendamment.
- Appliquez le code HTML en tant que texture :
- Préallouer l'espace de stockage des textures GPU.
- Importez l'instantané DOM en tant que texture.
- Synchronisez le DOM et les pixels.
Dessiner un élément HTML en tant que texture WebGL
Dans WebGL, les éléments HTML sont importés dans le GPU en tant que textures 2D à l'aide de texElementSubImage2D().
Préallouer l'espace de stockage des textures
Contrairement à un canevas 2D, qui gère automatiquement la mémoire de sauvegarde, un contexte WebGL nécessite une gestion explicite de la mémoire.
Avant d'importer des pixels DOM, vous devez préallouer de la mémoire GPU. Cela permet au navigateur d'effectuer des mises à jour rapides des sous-images sans déclencher de réallocations coûteuses de la mémoire GPU.
Préallouez la mémoire tampon avec les paramètres de taille sélectionnés et srcData défini sur null comme suit :
// 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;
}
Pour que la texture corresponde à la taille de mise en page naturelle de l'élément HTML, utilisez canvas.getElementImageDefaultSize() pour récupérer sa taille par défaut en pixels de la grille du canevas :
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
);
Importer l'instantané DOM en tant que texture
L'étape suivante consiste à importer l'élément HTML dans votre texture, dans votre boucle de rendu ou votre écouteur 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()`
);
// ...
};
Synchroniser la géométrie
Contrairement aux contextes 2D, le navigateur ne peut pas déduire automatiquement l'emplacement de la texture à l'écran dans un contexte 3D. Vous devez aligner manuellement les cadres de délimitation des tests de positionnement DOM et de l'accessibilité avec votre maillage 3D.
Pour ce faire, créez un DOMMatrix qui mappe la zone de bordure de l'élément à l'emplacement de pixel du canevas affiché, puis appliquez-le à l'aide de 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,
});
});
Étapes suivantes
- Comprendre les concepts techniques de base de HTML-in-Canvas.
- Découvrez comment afficher du code HTML dans un contexte 2D.
- Découvrez comment afficher du code HTML dans un canevas WebGPU.
- Découvrez les stratégies de remplacement.
- Signalez un problème sur GitHub pour nous faire part de vos commentaires.
- Consultez la collection de démonstrations HTML-in-Canvas de la communauté.