HTML-in-Canvas API memungkinkan Anda merender subtree DOM yang interaktif dan mudah diakses langsung ke konteks kanvas 2D. Baca ringkasan HTML-in-Canvas untuk mempelajari lebih lanjut API ini dan manfaatnya.
Panduan ini menunjukkan cara merender HTML ke dalam kanvas 2D. Merender HTML di kanvas 2D memerlukan langkah-langkah berikut:
- Siapkan kanvas Anda. Tetapkan atribut yang tepat secara deklaratif untuk memberi tahu browser bahwa browser harus merender HTML ke dalam kanvas. Penyiapan ini identik di seluruh konteks 2D, WebGL, dan WebGPU. Pelajari cara menyiapkan kanvas dan cara mendeklarasikan elemen HTML yang akan digambar secara independen.
- Gambar gambar elemen ke dalam kanvas.
- [Opsional] Sinkronkan DOM dan piksel.
Menggambar elemen HTML ke dalam kanvas 2D
Setelah kanvas siap dan elemen ditandai sebagai drawable, render elemen tersebut ke dalam konteks 2D menggunakan metode 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);
}
drawElementImage() mendukung bentuk 3 argumen, 5 argumen, 7 argumen, dan 9 argumen serta menerima parameter options opsional:
// 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);
| Formulir kelebihan beban | Parameter | Efek tata letak |
|---|---|---|
| Ukuran default | (element, dx, dy) |
Seluruh elemen dalam ukuran defaultnya, dengan sudut kiri atas di (dx, dy). |
| Kotak tujuan kustom | (element, dx, dy, dwidth, dheight) |
Menskalakan gambar elemen penuh ke area pandang dw × dh di kanvas. |
| Dipangkas, ukuran default | (element, sx, sy, swidth, sheight, dx, dy) |
Hanya area swidth × sheight yang dimulai dari (sx, sy), yang digambar pada ukuran default area tersebut (skala yang sama dengan formulir ukuran default). |
| Slice sumber ke tujuan | (element, sx, sy, swidth, sheight, dx, dy, dwidth, dheight) |
Memangkas elemen sumber mulai dari (sx, sy) dengan dimensi swidth × sheight, lalu memetakannya ke tujuan (dx, dy, dwidth, dheight). |
Menyinkronkan DOM dan piksel
Karena rendering <canvas> bersifat imperatif, sedangkan tata letak DOM dan gaya CSS bersifat reaktif, browser memerlukan mekanisme untuk menjaga piksel kanvas yang dirender, region hit-test interaktif, dan hierarki aksesibilitas tetap sinkron. Sebelum mempelajari cara menyinkronkan DOM dan piksel, pastikan Anda memahami peristiwa paint yang dipicu saat elemen DOM diupdate dan perlu digambar ulang.
Dalam konteks kanvas 2D, browser otomatis menyinkronkan koordinat tata letak elemen, batas aksesibilitas, dan hit-testing pointer dengan koordinat kanvas yang digambar.
Memperbarui geometri elemen secara manual
Dalam skenario lanjutan, Anda dapat memilih tidak ikut sinkronisasi geometri otomatis dan mengontrol transformasi spasial secara manual. Teruskan { preserveElementGeometry: true } ke drawElementImage() untuk mencegah browser mengganti koordinat hit test yang ada pada elemen secara otomatis:
// 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() akan otomatis memperbarui geometri ini. Demo ini menunjukkan bagaimana geometri menjadi tidak sinkron saat { preserveElementGeometry: true } ditetapkan.Langkah berikutnya
- Memahami konsep teknis inti di balik HTML-in-Canvas.
- Pelajari cara merender HTML di WebGL Canvas.
- Pelajari cara merender HTML di Canvas WebGPU.
- Pelajari strategi penggantian.
- Laporkan masalah di GitHub untuk memberikan masukan.
- Lihat koleksi demo HTML-in-Canvas oleh komunitas.