Mit der HTML-in-Canvas API können Sie interaktive, barrierefreie DOM-Unterbäume direkt in einem 2D-Canvas-Kontext rendern. Weitere Informationen zur API und ihren Vorteilen finden Sie in der Übersicht zu HTML-in-Canvas.
In diesem Leitfaden wird gezeigt, wie Sie HTML in einem 2D-Canvas rendern. Zum Rendern von HTML in einem 2D-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
- Zeichnen Sie das Elementbild in den Canvas.
- [Optional] Synchronisieren Sie das DOM und die Pixel.
HTML-Elemente in 2D-Canvas zeichnen
Sobald der Canvas bereit ist und Elemente als drawable markiert sind, rendern Sie sie mit der Methode drawElementImage() im 2D-Kontext.
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() unterstützt Formen mit 3, 5, 7 und 9 Argumenten und akzeptiert einen optionalen options-Parameter:
// 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);
| Formular für Überlastung | Parameter | Layouteffekt |
|---|---|---|
| Standardgröße | (element, dx, dy) |
Das gesamte Element in seiner Standardgröße, wobei sich die obere linke Ecke bei (dx, dy) befindet. |
| Feld „Benutzerdefiniertes Ziel“ | (element, dx, dy, dwidth, dheight) |
Skaliert das vollständige Elementbild in einen dw × dh-Darstellungsbereich auf der Leinwand. |
| Zugeschnitten, Standardgröße | (element, sx, sy, swidth, sheight, dx, dy) |
Nur der Bereich swidth × sheight, der bei (sx, sy) beginnt und in der Standardgröße dieses Bereichs gezeichnet wird (derselbe Maßstab wie das Formular in Standardgröße). |
| Quell-Slice zum Ziel | (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) |
Schneidet das Quellelement ab (sx, sy) mit den Abmessungen swidth × sheight zu und ordnet es dann dem Ziel (dx, dy, dwidth, dheight) zu. |
DOM und Pixel synchronisieren
Da das <canvas>-Rendering imperativ ist, während DOM-Layout und CSS-Styling reaktiv sind, benötigt der Browser einen Mechanismus, um die gerenderten Canvas-Pixel, interaktiven Trefferprüfungsbereiche und Barrierefreiheitsbäume synchron zu halten. Bevor Sie erfahren, wie Sie das DOM und die Pixel synchronisieren, sollten Sie sich mit dem paint-Ereignis vertraut machen, das ausgelöst wird, wenn DOM-Elemente aktualisiert und neu gezeichnet werden müssen.
In 2D-Canvas-Kontexten synchronisiert der Browser automatisch die Layoutkoordinaten, die Grenzen für die Barrierefreiheit im Internet und die Trefferprüfung für Zeiger des Elements mit den gezeichneten Canvas-Koordinaten.
Elementgeometrie manuell aktualisieren
In komplexeren Szenarien können Sie die automatische Geometriesynchronisierung deaktivieren und räumliche Transformationen manuell steuern. Übergeben Sie { preserveElementGeometry: true } an drawElementImage(), um zu verhindern, dass der Browser die vorhandenen Trefferprüfungskoordinaten des Elements automatisch überschreibt:
// 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 });
drawElementImage() automatisch aktualisiert. In dieser Demo wird gezeigt, wie die Geometrie nicht mehr synchron ist, wenn { preserveElementGeometry: true } festgelegt ist.