Merender HTML di kanvas WebGL memungkinkan Anda menggunakan subtree DOM aktif sebagai tekstur GPU dinamis, menerapkan efek shader ke DOM aktif, dan mengintegrasikan HTML interaktif ke dalam scene 3D.
Panduan ini menunjukkan cara merender HTML ke dalam kanvas WebGL. Pelajari lebih lanjut HTML-in-Canvas di ringkasan API.
Merender HTML di kanvas WebGL 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.
- Terapkan HTML sebagai tekstur:
- Pra-alokasikan penyimpanan tekstur GPU.
- Upload snapshot DOM sebagai tekstur.
- Menyinkronkan DOM dan piksel.
Menggambar elemen HTML sebagai tekstur WebGL
Di WebGL, elemen HTML diupload ke GPU sebagai tekstur 2D menggunakan texElementSubImage2D().
Melakukan pra-alokasi penyimpanan tekstur
Tidak seperti kanvas 2D, yang mengelola memori pendukung secara otomatis, konteks WebGL memerlukan pengelolaan memori eksplisit.
Sebelum mengupload piksel DOM, Anda harus mengalokasikan memori GPU terlebih dahulu. Hal ini memungkinkan browser melakukan update sub-gambar dengan cepat tanpa memicu realokasi memori GPU yang mahal.
Alokasikan buffer terlebih dahulu dengan parameter ukuran yang dipilih dan srcData ditetapkan ke null sebagai berikut:
// 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;
}
Agar tekstur sesuai dengan ukuran tata letak alami elemen HTML, gunakan canvas.getElementImageDefaultSize() untuk mengambil ukuran defaultnya dalam piksel petak kanvas:
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
);
Mengupload snapshot DOM sebagai tekstur
Langkah berikutnya adalah mengupload elemen HTML ke tekstur di dalam loop render atau pemroses paint.
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()`
);
// ...
};
Menyinkronkan geometri
Tidak seperti dalam konteks 2D, browser tidak dapat otomatis menyimpulkan tempat tekstur muncul di layar dalam konteks 3D. Anda harus menyelaraskan hit-test DOM dan kotak pembatas aksesibilitas dengan mesh 3D secara manual.
Untuk melakukannya, buat DOMMatrix yang memetakan kotak batas elemen ke lokasi piksel kanvas yang dirender, lalu terapkan menggunakan updateElementGeometry():
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,
});
});
Langkah berikutnya
- Memahami konsep teknis inti di balik HTML-in-Canvas.
- Pelajari cara merender HTML dalam konteks 2D.
- 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.