Chrome 150 dan 155 memperkenalkan beberapa perubahan pada HTML-in-Canvas API. Perubahan ini merespons masukan dari komunitas dan standar dengan tujuan untuk meningkatkan ergonomi API. Postingan blog ini menguraikan perubahan, dan cara memastikan penerapan Anda sudah yang terbaru.
Pembaruan ini mencakup penggantian nama atribut dan metode, yang memerlukan pra-alokasi memori tekstur eksplisit, dan memperbarui model sinkronisasi DOM. Selain itu, Uji Coba Origin HTML dalam Canvas kini diperpanjang. Berikut penjelasan tentang apa yang berubah, alasannya, dan cara memperbarui codebase Anda.
Perubahan di Chrome 150
Di Chrome 150, kami mengubah tanda tangan argumen di WebGL dan WebGPU untuk menghilangkan redundansi dan menyelaraskan dengan konvensi grafis modern.
WebGL
Kami menghapus argumen yang berlebihan (level, srcFormat, destType) dari texElementImage2D
(lihat diskusi WebGL untuk
detail selengkapnya):
// Old implementation (Chrome < 150)
const level = 0;
const internalFormat = gl.RGBA;
const srcFormat = gl.RGBA;
const destType = gl.UNSIGNED_BYTE;
gl.texElementImage2D(
gl.TEXTURE_2D,
level,
internalFormat,
srcFormat,
destType,
element
);
// New implementation (from Chrome 150)
const internalFormat = gl.RGBA8;
gl.texElementImage2D(gl.TEXTURE_2D, internalFormat, element);
WebGPU
Kami menstandardisasi parameter copyElementImageToTexture menjadi objek sourceDict dan destDict (lihat GPUWeb PR#6250):
// Old implementation (Chrome < 150)
GPUQueue.copyElementImageToTexture(
element,
width,
height,
{ texture: texture }
);
// New implementation (from Chrome 150)
const sourceDict = { source: element };
const destDict = {
destination: { texture: texture },
width: width,
height: height
};
GPUQueue.copyElementImageToTexture(sourceDict, destDict);
Perubahan di Chrome 155
Chrome 155 memperkenalkan penyempurnaan lebih lanjut berdasarkan masukan developer. Kami memperbarui nama metode, mewajibkan pra-alokasi memori tekstur eksplisit, mendukung subpohon DOM yang kompleks, dan memisahkan sinkronisasi DOM.
WebGPU
Metode WebGPU telah diganti namanya dari copyElementImageToTexture menjadi
drawElementImageToTexture. Selain penggantian nama, koordinat parameter diperluas (sourceX, sourceWidth), dan batas tujuan dikelompokkan ke dalam objek size (GPUExtent3D) standar:
// BEFORE (Chrome 150)
const sourceDict = {
source: myElement,
sx: 0,
sy: 0,
swidth: 100,
sheight: 100
};
const destDict = {
destination: { texture: myTexture },
width: 300,
height: 200
};
queue.copyElementImageToTexture(sourceDict, destDict);
// AFTER (Chrome 155+)
const sourceDict = {
source: myElement,
sourceX: 0,
sourceY: 0,
sourceWidth: 100,
sourceHeight: 100
};
const destDict = {
texture: myTexture,
size: { width: 300, height: 200 }
};
queue.drawElementImageToTexture(sourceDict, destDict);
WebGL
Ada tiga aspek perubahan di WebGL untuk HTML dalam Canvas:
- Nama metode berubah dari
texElementImage2DmenjaditexElementSubImage2D.` - Tanda tangan metode berubah; yang paling signifikan, metode ini menambahkan argumen
xoffsetdanyoffsetuntuk secara opsional mengizinkan penentuan offset ke dalam tekstur tujuan tempat elemen akan digambar. - Metode ini tidak lagi mengalokasikan penyimpanan buffer secara otomatis untuk tekstur tujuan; penyimpanan harus dialokasikan secara eksplisit sebelum menggunakan API. Hal ini mirip dengan perilaku
texSubImage2D.
// 1. Capture natural layout size of the element
const elementImage = canvas.captureElementImage(element);
// 2. Pre-allocate texture backing once (or when element resizes)
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA8,
Math.ceil(elementImage.width),
Math.ceil(elementImage.height),
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
null // null reserves VRAM without uploading pixels
);
// 3. Upload DOM into pre-allocated VRAM
gl.texElementSubImage2D(
gl.TEXTURE_2D,
0, // level
0, // xoffset
0, // yoffset
element // pass DOM element
);
Atribut kanvas dan elemen turunan drawable
Kami memperbarui cara Anda menyiapkan kanvas untuk merender HTML.
Mengganti nama layoutsubtree menjadi content="drawable"
Untuk menyelaraskan dengan konvensi penamaan atribut HTML, atribut layoutsubtree
boolean pada elemen <canvas> telah diganti namanya menjadi content="drawable" (lihat
Masalah WICG #169 untuk
pembahasan mendetail).
Atribut drawable untuk turunan
Sebelumnya, hanya turunan langsung kanvas yang dirender. Untuk mendukung hierarki
DOM yang kompleks tanpa meratakan markup, kini Anda dapat menambahkan atribut
drawable secara eksplisit ke elemen turunan mana pun yang ingin Anda gambar secara terpisah:
<!-- BEFORE -->
<canvas layoutsubtree>
<div id="badge">
<h2>Player Stats</h2>
<button id="actionBtn">Equip</button>
</div>
</canvas>
<!-- AFTER (Chrome 155+) -->
<canvas content="drawable">
<!-- Subtree A (Body and heading) -->
<div id="badge" drawable>
<h2>Player Stats</h2>
<!-- Subtree B (Excluded from Subtree A; drawn and animated independently) -->
<button id="actionBtn" drawable>Equip</button>
</div>
</canvas>
Elemen dengan drawable mencakup seluruh subpohonnya kecuali untuk turunan bertingkat
yang juga menentukan drawable. Hal ini memungkinkan penampung induk dan elemen turunan seperti tombol dianimasikan dan digambar dalam panggilan gambar terpisah.
Sinkronisasi pengujian hit
Sebelumnya, developer harus mengambil nilai yang ditampilkan dari metode menggambar dan
menyalurkannya ke element.style.transform. Metode drawElementImage() kini menampilkan
void, dan sinkronisasi bergantung pada konteks.
Konteks 2D: Sinkronisasi Otomatis
Di kanvas 2D, browser secara otomatis menyinkronkan batas uji hit DOM dan cincin fokus pembaca layar ke koordinat yang digambar. Anda dapat menghapus semua piping transformasi manual:
// BEFORE
const transform = ctx.drawElementImage(element, x, y);
element.style.transform = transform.toString();
// AFTER (Chrome 155+)
ctx.drawElementImage(element, x, y);
// No style update needed: position & hit-testing sync automatically
Untuk mengelola geometri secara manual dalam 2D, teruskan { preserveElementGeometry: true } ke
drawElementImage() dan terapkan transformasi menggunakan canvas.updateElementGeometry().
Konteks 3D: Vulgar updateElementGeometry()
Untuk menyinkronkan DOM dalam konteks WebGL atau WebGPU, buat transformasi DOMMatrix dan teruskan ke canvas.updateElementGeometry():
canvas.addEventListener('paint', () => {
// 1. Upload element snapshot to GPU texture
device.queue.drawElementImageToTexture({ source: element }, { texture });
// 2. Render 3D scene...
drawScene();
// 3. Construct transform matrix as needed
const canvasTransform = new DOMMatrix().translate(x, y);
// 4. Update DOM hit-testing and accessibility bounding boxes
canvas.updateElementGeometry(element, { canvasTransform });
});
Kompatibilitas lintas versi
Jika aplikasi Anda harus mendukung pengguna di beberapa versi Chrome selama periode transisi, periksa keberadaan metode yang diupdate pada prototipe mereka dan sesuaikan penerapan Anda.
Pastikan Anda menetapkan atribut elemen <canvas> yang benar untuk setiap versi browser:
// ============================================================================
// Cross-version canvas markup
// ============================================================================
if (!canvas.hasAttribute('content') && !canvas.hasAttribute('layoutsubtree')) {
if ('content' in HTMLCanvasElement.prototype) {
// Chrome 155+ (New standardized attribute)
canvas.setAttribute('content', 'drawable');
} else {
// Chrome < 155 (Legacy boolean attribute)
canvas.setAttribute('layoutsubtree', '');
}
}
Untuk konteks 2D, periksa nilai yang ditampilkan oleh drawElementImage() dan periksa atribut prototipe kanvas untuk mendukung kedua versi:
// ============================================================================
// Cross-version 2D drawing & synchronization
// ============================================================================
function draw2DElement(ctx, element, x, y) {
// Execute the 2D draw call
const result = ctx.drawElementImage(element, x, y);
if (result !== undefined && typeof result?.toString === 'function') {
// Chrome < 155: drawElementImage returned a DOMMatrix
// Requires manual transform piping to align DOM hit-test bounds:
element.style.transform = result.toString();
} else {
// Chrome 155+: drawElementImage returns void / undefined
// The browser automatically aligns DOM positioning, clicks, and a11y bounds!
// If you previously had element.style.transform logic here, clear it:
if (element.style.transform) {
element.style.transform = "";
}
}
}
Untuk WebGPU, gunakan tanda tangan dan nama metode yang kompatibel:
// ============================================================================
// WebGPU cross-version support
// ============================================================================
if ('drawElementImageToTexture' in GPUQueue.prototype) {
// Chrome 155+ (Latest implementation)
queue.drawElementImageToTexture(
{ source: element, sourceX: 0, sourceY: 0, sourceWidth: w, sourceHeight: h },
{ texture: myTexture, size: { width: w, height: h } }
);
} else if (typeof queue.copyElementImageToTexture === "function") {
// Chrome 150 - 154: Try the Chrome 150+ dictionary signature first,
// then fall back to the Chrome < 150 signature
try {
queue.copyElementImageToTexture(
{ source: element },
{ destination: { texture: myTexture }, width: w, height: h }
);
} catch (err) {
// Chrome < 150
queue.copyElementImageToTexture(element, { texture: myTexture });
}
}
Pastikan untuk memeriksa kompatibilitas browser untuk WebGL:
// ============================================================================
// WebGL cross-version support
// ============================================================================
if ('texElementSubImage2D' in WebGL2RenderingContext.prototype) {
// Chrome 155+ (Explicit pre-allocation + sub-image)
gl.texElementSubImage2D(gl.TEXTURE_2D, 0, 0, 0, element);
} else if (gl.texElementImage2D && gl.texElementImage2D.length === 3) {
// Chrome 150-154 (3-argument signature)
gl.texElementImage2D(gl.TEXTURE_2D, gl.RGBA8, element);
} else if (gl.texElementImage2D) {
// Chrome < 150 (6-argument signature)
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, element);
}
Perpanjangan Uji Coba Origin
Uji Coba Origin HTML-in-Canvas telah diperpanjang hingga Chrome 160. Pastikan untuk memperpanjang masa berlaku token uji coba origin Anda agar dapat terus menawarkan fitur HTML dalam Canvas kepada pengguna. Lihat artikel Uji Coba Origin untuk mengetahui detail selengkapnya.
Beri masukan
Beri tahu kami cara kerja update ini di aplikasi Anda dengan melaporkan masalah di repositori GitHub WICG. Bergabunglah dengan newsletter developer untuk terus mendapatkan info terbaru tentang berita HTML in Canvas.