Interfejs HTML-in-Canvas API umożliwia renderowanie interaktywnych, dostępnych poddrzew DOM bezpośrednio w kontekstach Canvas 2D, WebGL lub WebGPU.
W tym przewodniku opisujemy zagadnienia techniczne dotyczące HTML-in-Canvas, które są wspólne dla wszystkich kontekstów Canvas:
- Przygotowywanie obszaru roboczego do renderowania kodu HTML
- Omówienie poddrzewa
drawable - Informacje o zdarzeniu
paint - Aktualizowanie geometrii elementu
- Ułatwienia dostępu w przypadku HTML-in-Canvas
- Korzystanie ze strategii zastępczych
Przygotowywanie obszaru roboczego do renderowania kodu HTML
Aby renderować elementy HTML w elemencie <canvas>, skonfiguruj te 2 atrybuty:
- Ustaw
content="drawable"na<canvas>: spowoduje to, że element canvas będzie układać swoje elementy potomne DOM, zamiast traktować je wyłącznie jako ukrytą treść. - Ustaw
drawablena elementach docelowych: oznacza to element jako niezależny element główny renderowania, który może być renderowany na elemencie canvas.
<canvas id="mainCanvas" width="600" height="400" content="drawable">
<div id="parentElement" class="card" drawable>
<h2>Container Title</h2>
<p>Descriptive text inside the parent element.</p>
<!-- Nested drawable: excluded from parentElement and drawn independently -->
<button id="childElement" class="btn" drawable>Action Button</button>
</div>
</canvas>
Omówienie poddrzewa elementów rysowalnych
Podczas przygotowywania kodu HTML do renderowania w obszarze roboczym musisz zdecydować, które elementy mają być rysowane niezależnie. Każdy element drawable reprezentuje niezależny element główny rysowania i jego poddrzewo, które można narysować.
Poddrzewo rysowalne składa się z elementu z atrybutem drawable i wszystkich jego elementów podrzędnych, z wyłączeniem elementów podrzędnych, które również mają atrybut drawable, na przykład:
<canvas content="drawable">
<!-- Subtree A (Renders parent container and text) -->
<div id="parentElement" drawable>
<h2>Parent Card Heading</h2>
<p>Card body text content.</p>
<!-- Subtree B (Excluded from Subtree A and drawn separately) -->
<button id="nestedChildElement" drawable>
Clickable Button
</button>
</div>
</canvas>
| Element | Granica renderowania | Zachowanie |
|---|---|---|
#parentElement (poddrzewo A) |
Panel tła, nagłówek i akapit | Renderowane podczas wywoływania drawElementImage(parentElement, ...) |
#nestedChildElement (poddrzewo B) |
Powierzchnia przycisku i tekst | Wykluczone z poddrzewa #parentElement; renderowane w osobnym wywołaniu drawElementImage(nestedChildElement, ...) |
drawable jest zagnieżdżony w karcie drawable, a każdy z nich jest rysowany przez własne wywołanie drawElementImage().Zagnieżdżanie elementów rysowalnych pozwala zachować semantyczne relacje HTML, dając jednocześnie swobodę nakładania, pozycjonowania i animowania elementów podrzędnych niezależnie od siebie na scenie obszaru roboczego.
Zdarzenie paint
Interfejs HTML-in-Canvas API wprowadza zdarzenie paint. Przeglądarka automatycznie wysyła zdarzenie paint do elementu <canvas>, gdy zmienia się układ, tekst lub style CSS w dowolnym elemencie podrzędnym drawable.
canvas.addEventListener("paint", (event) => {
// Clear the viewport
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Redraw elements individually
ctx.drawElementImage(parentElement, 20, 20);
ctx.drawElementImage(childElement, 40, 90);
});
Zdarzenie paint wysyła instancję CanvasPaintEvent, która rozszerza standardowy DOM Event i ma właściwość changedElements zawierającą tylko te elementy podrzędne drawable, które zmieniły się wizualnie (np. zmiany stylu, przesunięcia układu, edycje tekstu lub zmiany stanu aktywności) od ostatniego renderowania.
canvas.addEventListener("paint", (event) => {
// Array of changed elements
for (const el of event.changedElements) {
console.log(`Element #${el.id} visually changed and needs repainting`);
}
});
Cykl życia ramki
Polecenia rysowania na elemencie canvas wykonywane w ramach zdarzenia paint pojawiają się w bieżącej aktualizacji renderowania, ale modyfikacje DOM wprowadzone w ramach zdarzenia paint są widoczne dopiero w następnej klatce:
canvas.addEventListener("paint", () => {
// Renders in the CURRENT rendering update:
ctx.drawElementImage(parentElement, 20, 20);
// Modifying DOM styles inside paint schedules a new layout cycle;
// changes will appear in the NEXT frame:
parentElement.style.backgroundColor = "#e0f2fe";
});
Zagnieżdżone obszary robocze
Jeśli strona zawiera zagnieżdżone elementy <canvas content="drawable">, przeglądarka wysyła zdarzenia paint w odwrotnej kolejności drzewa DOM (elementy podrzędne są uruchamiane przed elementami nadrzędnymi). Dzięki temu elementy podrzędne obszaru roboczego są renderowane, zanim zostaną połączone z elementami nadrzędnymi.
Załóżmy, że w poniższym przykładzie wewnętrzny element nestedElement musi zmienić się wizualnie (np. jego kolor tła CSS zmienia się, gdy użytkownik najeżdża na niego kursorem). Najpierw na obszarze roboczym nestedCanvas jest wywoływane zdarzenie paint. Jego detektor czyści bufor podrzędny i wywołuje funkcję ctx.drawElementImage(nestedElement, ...), aby wyrenderować zaktualizowany stan. Następnie zdarzenie paint jest wywoływane na stronie parentCanvas. Jego detektor rysuje na scenie wrapperElement (który zawiera już zaktualizowany obszar roboczy nestedCanvas).
<!-- Outer parent canvas -->
<canvas id="parentCanvas" width="800" height="600" content="drawable">
<!-- Wrapper container for nested content -->
<div id="wrapperElement" drawable>
<!-- Nested child canvas -->
<canvas id="nestedCanvas" width="300" height="200" content="drawable">
<div id="nestedElement" class="badge" drawable>
Inner Child Content
</div>
</canvas>
</div>
</canvas>
<script>
const parentCanvas = document.getElementById("parentCanvas");
const parentCtx = parentCanvas.getContext("2d");
const nestedCanvas = document.getElementById("nestedCanvas");
const nestedCtx = nestedCanvas.getContext("2d");
const nestedElement = document.getElementById("nestedElement");
const wrapperElement = document.getElementById("wrapperElement");
// ============================================================================
// 1. Child Canvas Listener (Fires FIRST)
// ============================================================================
nestedCanvas.addEventListener("paint", (event) => {
// Clear and redraw the child canvas with the updated inner element
nestedCtx.clearRect(0, 0, nestedCanvas.width, nestedCanvas.height);
nestedCtx.drawElementImage(nestedElement, 10, 10);
console.log("1. Child nested canvas rendered fresh pixels.");
});
// ============================================================================
// 2. Parent Canvas Listener (Fires SECOND)
// ============================================================================
parentCanvas.addEventListener("paint", (event) => {
// Clear and redraw the parent canvas scene
parentCtx.clearRect(0, 0, parentCanvas.width, parentCanvas.height);
// Draws the wrapper container (including the freshly painted nestedCanvas)
parentCtx.drawElementImage(wrapperElement, 50, 50);
console.log("2. Parent canvas composited the complete scene.");
});
</script>
<canvas content="drawable"> są zagnieżdżone, zdarzenia renderowania są wywoływane w odwrotnej kolejności drzewa: najpierw renderowany jest zagnieżdżony obszar roboczy, dzięki czemu nadrzędny obszar roboczy może narysować aktualne piksele.Wywołaj zdarzenie paint
Wywołaj requestPaint(), aby zaplanować pojedyncze zdarzenie paint w następnej klatce, nawet jeśli nie zmienił się tekst ani style DOM. Można go używać do renderowania interaktywnych scen z ruchomymi elementami, na przykład:
let animatedX = 0;
canvas.addEventListener("paint", () => {
animatedX += 1.5; // Move the element horizontally
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawElementImage(staticElement, 20, 20);
ctx.drawElementImage(movingElement, animatedX, 200);
// Request canvas paint on each rendering update for smooth animation
canvas.requestPaint();
});
canvas.requestPaint();
Aktualizowanie geometrii elementu
Gdy rysujesz element HTML na obszarze roboczym, kod rysowania określa, gdzie element się pojawi i jak duży będzie. W przeciwieństwie do zwykłej zawartości HTML pozycji i rozmiaru elementu na ekranie, czyli jego geometrii, nie można określić na podstawie samego obliczonego stylu. Przeglądarka potrzebuje geometrii elementu, aby:
- wysyłać zdarzenia wejściowe, takie jak kliknięcia, dotknięcia i ruchy wskaźnika, do odpowiedniego elementu; Nazywa się to testem pozycji wskaźnika.
- Zwracanie dokładnych wyników z zapytań dotyczących układu, takich jak
getBoundingClientRect(). - zgłaszać granice elementu technologiom wspomagającym osoby z niepełnosprawnością, takim jak lupy ekranowe;
W trybie 2D drawElementImage() domyślnie automatycznie aktualizuje geometrię. Argumenty, które do niego przekazujesz, wraz z obliczonym stylem elementu i bieżącym przekształceniem kontekstu, wystarczą do określenia, gdzie element się pojawi.
W kontekstach WebGL i WebGPU przeglądarka nie może określić geometrii. Element HTML jest kopiowany do tekstury, a program cieniujący może następnie zmapować tę teksturę na scenę w dowolny sposób. Aby poinformować przeglądarkę, gdzie pojawia się element, przekaż przekształcenie do updateElementGeometry().
updateElementGeometry(), przeglądarka nie będzie już wiedzieć, gdzie znajdują się elementy HTML na karcie 3D. Karta się obraca, ale kliknięcia nadal trafiają tam, gdzie była wcześniej.Aby zaktualizować geometrię, przekaż do metody przekształcenie przestrzenne. Dowiedz się, jak utworzyć przekształcenie w różnych kontekstach:
- Synchronizowanie geometrii w trybie 2D
- Synchronizowanie geometrii w WebGL.
- Synchronizowanie geometrii w WebGPU.
Zarządzanie kolejnością stosu testu pozycji wskaźnika
Domyślnie za każdym razem, gdy geometria elementu jest aktualizowana, przeglądarka przenosi go na górę stosu interakcji (ostatnio narysowany = najwyższy cel kliknięcia). Możesz kontrolować to zachowanie za pomocą preserveHitTestOrder:
// Updates the backdrop without stealing clicks from foreground elements
canvas.updateElementGeometry(backgroundElement, {
canvasTransform: customTransform,
preserveHitTestOrder: true
});
| Opcja | Zachowanie | Przypadek użycia |
|---|---|---|
preserveHitTestOrder: false (domyślnie) |
Przenosi element na górę stosu testu pozycji wskaźnika. | Elementy na pierwszym planie, które powinny być klikane jako pierwsze. |
preserveHitTestOrder: true |
Pozostawia element na bieżącym poziomie priorytetu stosu. | Elementy tła, które należy zaktualizować po elementach pierwszego planu. |
Resetuj geometrię
Aby cofnąć rysowanie elementu bez usuwania go z DOM, wywołaj canvas.clearElementGeometry(). Spowoduje to zresetowanie przekształcenia obszaru roboczego elementu i oznaczenie go jako poza ekranem w drzewie ułatwień dostępu:
// Remove from canvas hit-testing and mark as offscreen
canvas.clearElementGeometry(childElement);
Rozmiary i jednostki
Gdy rysujesz kod HTML na elemencie canvas, przeglądarka działa jednocześnie w 3 układach współrzędnych: pikselach CSS, pikselach urządzenia i pikselach siatki elementu canvas.
Piksele CSS służą do pomiaru i pozycjonowania treści podczas tworzenia układu. Następnie przeglądarka skaluje je o devicePixelRatio, aby zrasteryzować stronę na piksele urządzenia fizycznego. Ponieważ piksele CSS są jednostką logiczną, pozycje i rozmiary często kończą się jako ułamki piksela urządzenia (np. 10,5 piksela CSS × DPR 1,5 = 15,75 piksela urządzenia). Ekran może wyświetlać tylko całe piksele, więc przeglądarka musi rozwiązać problem z wszystkim, co znajduje się między nimi. Dzieje się tak na 2 sposoby:
- Przyciąganie: granice pól, obramowania i przesunięcia warstw są zaokrąglane do najbliższego pełnego piksela urządzenia, dzięki czemu pozostają wyraźne.
- Wygładzanie: w przypadku glifów tekstowych, krzywych i przekształconych krawędzi częściowe pokrycie jest mieszane z sąsiednimi pikselami, dzięki czemu nadal wyglądają gładko i znajdują się we właściwym miejscu.
Element <canvas> ma własną siatkę pikseli określoną przez atrybuty width i height, która jest niezależna od pikseli CSS i pikseli urządzenia. Aby go wyświetlić, przeglądarka ponownie próbkuje bitmapę obszaru roboczego na siatce pikseli fizycznych, łącząc sąsiadujące piksele obszaru roboczego, aby wypełnić każdy piksel urządzenia. Aby dowiedzieć się, jak przeglądarka mapuje piksele CSS, canvas i urządzenia, przeczytaj artykuł Renderowanie z dokładnością co do piksela za pomocą devicePixelContentBox.
Wszystkie elementy HTML drawable są rozmieszczone w pikselach CSS. Treści narysowane na elemencie canvas mogą przejść przez 2 konwersje: z pikseli CSS na siatkę elementu canvas, a następnie z siatki elementu canvas na piksele fizyczne. Każdy krok, który nie jest dokładnie dopasowany, dodaje kolejną rundę mieszania, co może spowodować, że wynik będzie wyglądać na rozmyty. Aby tego uniknąć, dopasuj siatkę obszaru roboczego do siatki pikseli fizycznych. Ma to 2 cele:
- Spójne renderowanie: jeśli element canvas jest mapowany w stosunku 1:1 na piksele fizyczne, konwersja pikseli CSS na piksele elementu canvas daje taki sam wynik jak konwersja pikseli CSS na piksele fizyczne w przeglądarce w przypadku zwykłego kodu HTML.
- Brak dodatkowego mieszania: jeśli obszar roboczy jest mapowany w stosunku 1:1 na piksele fizyczne, konwersja na piksele urządzenia nie powoduje rozmycia.
Poniższy obraz przedstawia konwersję pikseli, która powoduje rozmycie treści. Te 3 siatki nie są wyrównane: element canvas ma wymiary 360 × 180 pikseli CSS, a rozmiar obszaru roboczego to 300 × 150 pikseli siatki obszaru roboczego. Przy współczynniku pikseli urządzenia wynoszącym 1, 5 obszar roboczy obejmuje 540 × 270 pikseli urządzenia. Jeden piksel CSS obejmuje 1,5 piksela urządzenia, a jeden piksel obszaru roboczego obejmuje 1,2 piksela CSS, czyli 1,8 piksela urządzenia (panel 1). Po narysowaniu okręgu jego położenie i promień są wyrażone w pikselach obszaru roboczego, a nie w pikselach CSS, więc przeglądarka rysuje go na mapie bitowej obszaru roboczego o wymiarach 300 × 150 i wygładza krawędź (panel 2). Aby wyświetlić obszar roboczy, przeglądarka rozciąga tę bitmapę na 540 × 270 pikseli urządzenia, więc musi przeprowadzić interpolację: każdy piksel urządzenia przyjmuje ważoną kombinację najbliższych pikseli obszaru roboczego, które zawierają już wygładzoną krawędź. Krawędź jest mieszana po raz drugi i rozciąga się na kilka pikseli urządzenia, przez co okrąg wygląda na rozmyty (panel 3). Można tego uniknąć, jeśli siatka obszaru roboczego odpowiada pikselom urządzenia w stosunku 1:1. Przeglądarka wygładzi krawędź tylko raz, bezpośrednio na siatce urządzenia, i wyświetli bitmapę bez ponownego próbkowania, dzięki czemu krawędź pozostanie ostra (panel 4):
Aby uzyskać wyraźny obraz, siatka obszaru roboczego musi odpowiadać liczbie pikseli urządzenia, które obejmuje obszar roboczy: 540 × 270 w poprzednim przykładzie.
Zmienianie rozmiaru siatki obszaru roboczego za pomocą obserwatora zmiany rozmiaru
Odpowiedni rozmiar siatki zależy od urządzenia i może się zmieniać, gdy zmienia się układ, gdy użytkownik powiększa stronę lub gdy użytkownik przenosi okno na inny wyświetlacz. Zamiast kodować na stałe rozmiar siatki, pozwól przeglądarce określić, jaki powinien być.
Aby siatka obszaru roboczego była zsynchronizowana z obszarem roboczym na ekranie, zawsze ustawiaj jej rozmiar na ResizeObserver i dostosuj siatkę obszaru roboczego do devicePixelContentBoxSize:
const observer = new ResizeObserver(([entry]) => {
const dpc = entry.devicePixelContentBoxSize;
canvas.width = dpc ? dpc[0].inlineSize : Math.round(entry.contentRect.width * window.devicePixelRatio);
canvas.height = dpc ? dpc[0].blockSize : Math.round(entry.contentRect.height * window.devicePixelRatio);
});
const supportsDevicePixelContentBox =
typeof ResizeObserverEntry !== 'undefined' &&
'devicePixelContentBoxSize' in ResizeObserverEntry.prototype;
const options = supportsDevicePixelContentBox ? { box: 'device-pixel-content-box' } : {};
observer.observe(canvas, options);
Konwertowanie pikseli CSS na współrzędne siatki obszaru roboczego
Moduł obsługi paint często łączy pomiary DOM z wywołaniami rysowania, np. aby ustawić element na podstawie jego rozmiaru. Te 2 typy korzystają z różnych jednostek:
- Piksele obszaru roboczego opisują siatkę obszaru roboczego, której rozmiar jest określany przez
canvas.widthicanvas.height. Na przykład parametrydx,dy,dwidthidheightmetod rysowaniadrawElementImage()lub inne parametry interfejsów API elementu canvas, takie jakfillRect()itranslate(). - Piksele CSS opisują stronę. Pomiary DOM, takie jak
offsetWidthiclientWidth, oraz współrzędne zdarzenia wskaźnika, takie jakoffsetX, są podawane w pikselach CSS.
Oto przegląd jednostek używanych przez różne parametry interfejsu API:
| Wartość | Jednostki |
|---|---|
canvas.width i canvas.height |
Piksele siatki obszaru roboczego |
Parametry rysunku 2D, w tym dx, dy, dwidth i dheight z drawElementImage() |
Piksele siatki obszaru roboczego |
width i height zwrócone przez: canvas.getElementImageDefaultSize() |
Piksele siatki obszaru roboczego |
Prostokąty źródłowe: sx, sy, swidth i sheight z drawElementImage() i texElementSubImage2D(); sourceX, sourceY, sourceWidth i sourceHeight z drawElementImageToTexture() |
piksele CSS |
Rozmiary tekstur: width i height opcje z texElementSubImage2D(); size z drawElementImageToTexture() |
Piksele tekstury. Domyślnie rozmiar elementu w pikselach siatki obszaru roboczego, zaokrąglony w górę. |
Geometria elementu: getElementTransform() oraz opcje canvasTransform i canvasClip w updateElementGeometry() |
piksele CSS, |
pomiary DOM, takie jak offsetWidth, clientWidth, getBoundingClientRect(), współrzędne zdarzenia wskaźnika i contentBoxSize wpisu obserwatora zmiany rozmiaru; |
piksele CSS, |
devicePixelContentBoxSize wpisu obserwatora zmiany rozmiaru |
Piksele urządzenia |
Jeśli użyjesz nieprawidłowych jednostek, rozmiar treści HTML narysowanych na elemencie canvas może nie spełniać Twoich oczekiwań. Podczas rysowania kodu HTML na elemencie canvas musisz przekonwertować wartość piksela CSS na piksele siatki elementu canvas. Aby to zrobić, oblicz stosunek rozmiaru siatki obszaru roboczego do rozmiaru CSS obszaru roboczego: canvas.width / cssContentWidth w poziomie i canvas.height / cssContentHeight w pionie. Obserwator zmiany rozmiaru to wygodne miejsce do obliczenia współczynnika w ten sposób:
// The number of canvas grid pixels per CSS pixel
let scaleX = 1;
let scaleY = 1;
const observer = new ResizeObserver(([entry]) => {
const dpc = entry.devicePixelContentBoxSize;
const cssContentWidth = entry.contentRect.width;
const cssContentHeight = entry.contentRect.height;
// Best practice: make the canvas grid match the physical pixel grid
if (dpc) {
canvas.width = dpc[0].inlineSize;
canvas.height = dpc[0].blockSize;
} else {
canvas.width = Math.round(cssContentWidth * window.devicePixelRatio);
canvas.height = Math.round(cssContentHeight * window.devicePixelRatio);
}
scaleX = canvas.width / cssContentWidth;
scaleY = canvas.height / cssContentHeight;
});
const supportsDevicePixelContentBox =
typeof ResizeObserverEntry !== 'undefined' &&
'devicePixelContentBoxSize' in ResizeObserverEntry.prototype;
const options = supportsDevicePixelContentBox ? { box: 'device-pixel-content-box' } : {};
observer.observe(canvas, options);
Następnie pomnóż wartości pikseli CSS przez scaleX i scaleY, zanim przekażesz je do metody rysowania. Aby na przykład wyśrodkować element rysowalny w obszarze roboczym:
const ctx = canvas.getContext('2d');
const card = document.getElementById('card');
canvas.onpaint = () => {
ctx.reset();
// offsetWidth and offsetHeight are in CSS pixels.
// Convert them to canvas grid coordinates.
const width = card.offsetWidth * scaleX;
const height = card.offsetHeight * scaleY;
const x = (canvas.width - width) / 2;
const y = (canvas.height - height) / 2;
// drawElementImage() takes canvas grid coordinates.
ctx.drawElementImage(card, x, y);
};
Na koniec, ponieważ drawElementImage() rysuje obramowanie elementu, użyj box-sizing: border-box, aby uwzględnić dopełnienie i obramowanie w width i height karty, dzięki czemu karta będzie rysowana w ustawionym przez Ciebie rozmiarze:
#card {
/* Make width and height include padding and border */
box-sizing: border-box;
width: 200px;
padding: 16px;
}
Ułatwienia dostępu do elementów HTML w Canvas
Zasadniczo treść HTML elementu <canvas content="drawable"> jest udostępniana na potrzeby ułatwień dostępu w taki sam sposób jak zwykły DOM, co oznacza, że jest reprezentowana w drzewie ułatwień dostępu, chyba że zostanie wyraźnie ukryta za pomocą atrybutów takich jak aria-hidden="true" lub inert. Istnieje jednak jeden kluczowy wyjątek: element drawable, którego wyrenderowana geometria nie została jeszcze ustalona lub zaktualizowana.
Element drawable w elemencie <canvas content="drawable"> nie ma wyrenderowanej geometrii, jeśli:
- Nie został jeszcze wyrenderowany za pomocą
drawElementImage(), który domyślnie automatycznie aktualizuje geometrię. - Jego geometria nie została wyraźnie zaktualizowana za pomocą
updateElementGeometry().
Jeśli element drawable nie ma wyrenderowanej geometrii, ten element drawable i jego poddrzewo drawable są zgłaszane do drzewa ułatwień dostępu bez informacji o geometrii. Jest to przydatne, ponieważ pozwala na przykład czytnikom ekranu na dostęp do treści semantycznych, a jednocześnie sygnalizuje wizualnym narzędziom wspomagającym (takim jak lupy), aby odfiltrowywały nienarysowane elementy.
Poniższy przykład zachowuje semantykę rysunku, obrazu i podpisu, ale obraz i rysunek są rysowane osobno:
<canvas id="canvas" width="400" height="300" content="drawable">
<figure id="figure">
<img drawable id="image" src="..." alt="image alt text" />
<figcaption drawable id="caption">A caption</figcaption>
</figure>
</canvas>
<script>
const ctx = canvas.getContext('2d');
canvas.onpaint = () => {
ctx.reset();
// Note: Because `preserveElementGeometry` defaults to false, the
// `drawElementImage` call automatically updates geometry, ensuring
// the image and caption have geometry information for accessibility.
ctx.drawElementImage(image, 0, 0);
ctx.drawElementImage(caption, 0, 200);
};
</script>
Strategie zastępcze
Interfejs HTML-in-Canvas API został wprowadzony w Chrome 157 i może nie być obsługiwany we wszystkich przeglądarkach. Aby mieć pewność, że Twoje rozwiązanie działa bezproblemowo u wszystkich użytkowników, sprawdź, czy przeglądarka obsługuje interfejs API, i w razie potrzeby skorzystaj z alternatywnego rozwiązania:
export function supportsHtmlInCanvas() {
if (typeof document === 'undefined') return false;
const canvas = document.createElement('canvas');
canvas.setAttribute('content', 'drawable');
return canvas.content === 'drawable';
}
Jeśli interfejs API nie jest obsługiwany, możesz wybrać jedną z tych alternatyw w zależności od celów implementacji:
- alternatywny interfejs użytkownika,
- Pływające nakładki HTML
- Biblioteka three-html-render
- html2canvas
- dom-to-image
Dalsze kroki
- Dowiedz się, jak renderować kod HTML w kontekście 2D.
- Dowiedz się, jak renderować kod HTML w obszarze roboczym WebGL.
- Dowiedz się, jak renderować kod HTML w elemencie 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ść.