Als je HTML rendert in een WebGL-canvas, kun je live DOM-subtrees gebruiken als dynamische GPU-texturen, shader-effecten toepassen op de live DOM en interactieve HTML integreren in 3D-scènes.
In deze handleiding wordt uitgelegd hoe u HTML rendert in een WebGL-canvas. Meer informatie over HTML-in-Canvas vind je in het API-overzicht.
Voor de weergave van HTML in een WebGL-canvas zijn de volgende stappen vereist:
- Bereid je canvas voor. Stel de juiste kenmerken declaratief in om de browser te laten weten dat deze HTML moet renderen in een canvas. Deze instelling is identiek voor 2D-, WebGL- en WebGPU-contexten. Meer informatie over hoe je je canvas instelt en hoe je HTML-elementen declareert die onafhankelijk moeten worden getekend.
- Pas de HTML toe als textuur:
- Wijs GPU-textuuropslag vooraf toe.
- Upload de DOM-momentopname als een textuur.
- Synchroniseer het DOM en de pixels.
Een HTML-element tekenen als een WebGL-textuur
In WebGL worden HTML-elementen geüpload naar de GPU als 2D-texturen met texElementSubImage2D().
Textuuropslag vooraf toewijzen
In tegenstelling tot een 2D-canvas, dat het back-upgeheugen automatisch beheert, vereist een WebGL-context expliciet geheugenbeheer.
Voordat je DOM-pixels uploadt, moet je GPU-geheugen vooraf toewijzen. Zo kan de browser snelle updates van subafbeeldingen uitvoeren zonder dure herallocaties van GPU-geheugen te activeren.
Wijs de buffer vooraf toe met de geselecteerde grootteparameters en srcData ingesteld op null:
// 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;
}
Als je wilt dat de textuur overeenkomt met de natuurlijke vormgevingsgrootte van het HTML-element, gebruik je canvas.getElementImageDefaultSize() om de standaardgrootte op te halen in canvasrasterpixels:
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
);
De DOM-momentopname uploaden als textuur
De volgende stap is het HTML-element uploaden naar uw textuur in uw render-loop of paint-listener.
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()`
);
// ...
};
Geometrie synchroniseren
In tegenstelling tot 2D-contexten kan de browser niet automatisch afleiden waar de textuur op het scherm verschijnt in een 3D-context. Je moet DOM-hit-testing en toegankelijkheidsbegrenzingsvakken handmatig uitlijnen met je 3D-mesh.
Maak hiervoor een DOMMatrix die het randvak van het element toewijst aan de gerenderde canvaspixellocatie en pas deze toe met 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,
});
});
Volgende stappen
- Inzicht krijgen in de technische kernconcepten achter HTML-in-Canvas.
- Meer informatie over hoe je HTML rendert in een 2D-context.
- Meer informatie over hoe je HTML rendert in een WebGPU-canvas.
- Meer informatie over terugvalstrategieën.
- Dien een probleem in op GitHub om je feedback te delen.
- Ga naar de verzameling HTML-in-Canvas-demo's van de community.