Wenn Sie HTML in einem WebGL-Canvas rendern, können Sie Live-DOM-Unterbäume als dynamische GPU-Texturen verwenden, Shader-Effekte auf das Live-DOM anwenden und interaktives HTML in 3D-Szenen einbinden.
In diesem Leitfaden wird gezeigt, wie HTML in einem WebGL-Canvas gerendert wird. Weitere Informationen zu HTML-in-Canvas finden Sie in der API-Übersicht.
Zum Rendern von HTML in einem WebGL-Canvas sind die folgenden Schritte erforderlich:
- Arbeitsfläche vorbereiten Legen Sie die richtigen Attribute deklarativ fest, damit der Browser weiß, dass er HTML in einem Canvas rendern soll. Diese Einrichtung ist für 2D-, WebGL- und WebGPU-Kontexte identisch. Informationen zum Einrichten des Canvas und zum Deklarieren von HTML-Elementen, die unabhängig voneinander gezeichnet werden sollen
- Wenden Sie den HTML-Code als Textur an:
- GPU-Texturspeicher vorab zuweisen.
- Laden Sie den DOM-Snapshot als Textur hoch.
- Synchronisieren Sie das DOM und die Pixel.
HTML-Element als WebGL-Textur zeichnen
In WebGL werden HTML-Elemente mit texElementSubImage2D() als 2D-Texturen auf die GPU hochgeladen.
Texturspeicher vorab zuweisen
Im Gegensatz zu einem 2D-Canvas, bei dem der zugrunde liegende Speicher automatisch verwaltet wird, ist für einen WebGL-Kontext eine explizite Speicherverwaltung erforderlich.
Bevor Sie DOM-Pixel hochladen, müssen Sie GPU-Speicher vorab zuweisen. So kann der Browser schnelle Updates von Teilbildern durchführen, ohne dass teure Neuzuweisungen von GPU-Arbeitsspeicher ausgelöst werden.
Weisen Sie dem Zwischenspeicher vorab die ausgewählten Größenparameter zu und setzen Sie srcData auf 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;
}
Damit die Textur der natürlichen Layoutgröße des HTML-Elements entspricht, verwenden Sie canvas.getElementImageDefaultSize(), um die Standardgröße in Canvas-Rasterpixeln abzurufen:
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
);
DOM-Snapshot als Textur hochladen
Im nächsten Schritt laden Sie das HTML-Element in Ihre Textur in Ihrer Render-Schleife oder Ihrem paint-Listener hoch.
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 synchronisieren
Im Gegensatz zu 2D-Kontexten kann der Browser in einem 3D-Kontext nicht automatisch ableiten, wo die Textur auf dem Bildschirm angezeigt wird. Sie müssen die DOM-Trefferprüfung und die Begrenzungsrahmen für die Barrierefreiheit im Internet manuell an Ihr 3D-Mesh anpassen.
Erstellen Sie dazu eine DOMMatrix, die die Rahmenbox des Elements der gerenderten Canvas-Pixelposition zuordnet, und wenden Sie sie mit updateElementGeometry() an:
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,
});
});
Nächste Schritte
- Grundlegende technische Konzepte von HTML-in-Canvas
- HTML in einem 2D-Kontext rendern
- Weitere Informationen zum Rendern von HTML in einem WebGPU-Canvas
- Informationen zu Fallback-Strategien
- Melden Sie ein Problem auf GitHub, um uns Feedback zu geben.
- Sehen Sie sich die HTML-in-Canvas-Demosammlung der Community an.