Interfejs HTML-in-Canvas API umożliwia renderowanie interaktywnych, dostępnych poddrzew DOM bezpośrednio w kontekście Canvas 2D. Aby dowiedzieć się więcej o interfejsie API i jego zaletach, przeczytaj omówienie HTML-in-Canvas.
Z tego przewodnika dowiesz się, jak renderować kod HTML na elemencie canvas 2D. Renderowanie kodu HTML w elemencie canvas 2D wymaga wykonania tych czynności:
- Przygotuj obszar roboczy. Deklaratywnie ustaw odpowiednie atrybuty, aby poinformować przeglądarkę, że powinna renderować kod HTML w elemencie canvas. Ta konfiguracja jest identyczna w kontekstach 2D, WebGL i WebGPU. Dowiedz się, jak skonfigurować obszar roboczy i jak zadeklarować elementy HTML, które mają być rysowane niezależnie.
- Narysuj obraz elementu na obszarze roboczym.
- [Opcjonalnie] Zsynchronizuj DOM i piksele.
Rysowanie elementów HTML na obszarze roboczym 2D
Gdy obszar roboczy jest gotowy, a elementy są oznaczone jako drawable, wyrenderuj je w kontekście 2D za pomocą metody drawElementImage().
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);
}
Funkcja drawElementImage() obsługuje formy z 3, 5, 7 i 9 argumentami oraz akceptuje opcjonalny parametr options:
// 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);
| Formularz przeciążenia | Parametry | Efekt układu |
|---|---|---|
| Rozmiar domyślny | (element, dx, dy) |
Cały element w domyślnym rozmiarze, z lewym górnym rogiem w punkcie (dx, dy). |
| Pole niestandardowego miejsca docelowego | (element, dx, dy, dwidth, dheight) |
Skaluje pełny obraz elementu do widocznego obszaru dw × dh na obszarze roboczym. |
| Przycięty, rozmiar domyślny | (element, sx, sy, swidth, sheight, dx, dy) |
Tylko obszar swidth × sheight zaczynający się od (sx, sy), narysowany w domyślnym rozmiarze tego obszaru (w tej samej skali co formularz o domyślnym rozmiarze). |
| Wycinek źródłowy do miejsca docelowego | (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) |
Przycina element źródłowy, zaczynając od (sx, sy) z wymiarami swidth × sheight, a następnie mapuje go do miejsca docelowego (dx, dy, dwidth, dheight). |
Synchronizowanie modelu DOM i pikseli
Ponieważ renderowanie <canvas> jest imperatywne, a układ DOM i style CSS są reaktywne, przeglądarka potrzebuje mechanizmu, który synchronizuje wyrenderowane piksele obszaru roboczego, interaktywne regiony testu pozycji wskaźnika i drzewa ułatwień dostępu. Zanim dowiesz się, jak synchronizować DOM i piksele, zapoznaj się ze zdarzeniem paint, które jest wywoływane, gdy elementy DOM są aktualizowane i wymagają ponownego narysowania.
W kontekstach canvas 2D przeglądarka automatycznie synchronizuje współrzędne układu elementu, granice ułatwień dostępu i test pozycji wskaźnika ze współrzędnymi narysowanego elementu canvas.
Ręczne aktualizowanie geometrii elementu
W bardziej zaawansowanych scenariuszach możesz zrezygnować z automatycznej synchronizacji geometrii i ręcznie kontrolować przekształcenia przestrzenne. Przekaż { preserveElementGeometry: true } do drawElementImage(), aby uniemożliwić przeglądarce automatyczne zastępowanie istniejących współrzędnych testu pozycji wskaźnika elementu:
// 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() automatycznie aktualizuje tę geometrię. Ten przykład pokazuje, jak geometria przestaje być zsynchronizowana, gdy ustawiona jest właściwość { preserveElementGeometry: true }.Dalsze kroki
- Poznaj podstawowe zagadnienia techniczne związane z elementami HTML w elemencie Canvas.
- Dowiedz się, jak renderować kod HTML w elemencie Canvas WebGL.
- Dowiedz się, jak renderować kod HTML w Canvas WebGPU.
- Dowiedz się więcej o strategiach zastępczych.
- Aby podzielić się opinią, zgłoś problem na GitHubie.
- Zapoznaj się z kolekcją demonstracyjną HTML-in-Canvas utworzoną przez społeczność.