أجرينا عدة تغييرات على واجهة برمجة التطبيقات HTML-in-Canvas في الإصدارَين 150 و155 من Chrome. وقد تم إجراء هذه التغييرات استجابةً لملاحظات المنتدى والمعايير بهدف تحسين سهولة استخدام واجهة برمجة التطبيقات. توضّح مشاركة المدونة هذه التغييرات وكيفية التأكّد من أنّ عملية التنفيذ تتوافق معها.
تشمل التحديثات إعادة تسمية السمات والطرق، واشتراط التخصيص المسبق الصريح لذاكرة النسيج، وتعديل نماذج مزامنة DOM. بالإضافة إلى ذلك، تم الآن تمديد الإصدار التجريبي من HTML في Canvas. في ما يلي توضيح للتغييرات التي سنجريها وأسبابها وكيفية تعديل قاعدة الرموز البرمجية.
التغييرات في الإصدار 150 من Chrome
في الإصدار 150 من Chrome، غيّرنا تواقيع الوسيطات في WebGL وWebGPU لإزالة التكرار والتوافق مع معايير الرسومات الحديثة.
WebGL
أزلنا الوسيطات المكرّرة (level وsrcFormat وdestType) من texElementImage2D (راجِع مناقشة WebGL للحصول على مزيد من التفاصيل):
// 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
لقد وحّدنا copyElementImageToTextureالمَعلمات في الكائنَين sourceDict وdestDict (راجِع 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);
التغييرات في الإصدار 155 من Chrome
يقدّم الإصدار 155 من Chrome المزيد من التحسينات استنادًا إلى ملاحظات المطوّرين. نعمل على تعديل أسماء الطرق، ونطلب تخصيصًا مسبقًا صريحًا لذاكرة النسيج، ونوفّر إمكانية استخدام أجزاء معقّدة من شجرة نموذج المستند (DOM)، ونفصل مزامنة نموذج المستند (DOM).
WebGPU
تمت إعادة تسمية طريقة WebGPU من copyElementImageToTexture إلى drawElementImageToTexture. بالإضافة إلى إعادة التسمية، يتم توسيع إحداثيات المَعلمات (sourceX، sourceWidth)، ويتم تجميع حدود الوجهة في عنصر size (GPUExtent3D) عادي:
// 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
هناك ثلاثة جوانب للتغييرات في WebGL لـ HTML-in-Canvas:
- يتغيّر اسم الطريقة من
texElementImage2DإلىtexElementSubImage2D. - تتغيّر توقيع الطريقة، وبشكل أساسي، تتم إضافة الوسيطتَين
xoffsetوyoffsetللسماح اختياريًا بتحديد إزاحة في نسيج الوجهة يتم فيها رسم العنصر. - لم تعُد الطريقة تخصّص تلقائيًا مساحة تخزين مؤقتة للنسيج الوجهة، بل يجب تخصيص مساحة التخزين بشكل صريح قبل استخدام واجهة برمجة التطبيقات. وهذا مشابه لسلوك
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
);
سمات لوحة العرض والعناصر الفرعية القابلة للرسم
نحن بصدد تعديل طريقة إعداد لوحة العرض لتقديم محتوى HTML.
إعادة تسمية "layoutsubtree" إلى "content="drawable""
تماشيًا مع اصطلاحات تسمية سمات HTML، تمّت إعادة تسمية السمة المنطقية layoutsubtree في العنصر <canvas> إلى content="drawable" (راجِع المشكلة رقم 169 في WICG للحصول على مناقشة تفصيلية).
السمة drawable للعناصر الفرعية
في السابق، كان يتم عرض العناصر الثانوية المباشرة للوحة العرض فقط. لإتاحة استخدام تسلسلات هرمية معقّدة في نموذج المستند (DOM) بدون تسوية الترميز، يمكنك الآن إضافة السمة drawable بشكل صريح إلى أي عنصر فرعي تريد رسمه بشكل مستقل:
<!-- 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>
يلتقط العنصر الذي يتضمّن drawable شجرة فرعية كاملة باستثناء العناصر التابعة المتداخلة التي تحدّد drawable أيضًا. يتيح ذلك تحريك الحاويات الرئيسية والعناصر الفرعية، مثل الأزرار، ورسمها في طلبات رسم منفصلة.
مزامنة اختبارات النتائج
في السابق، كان على المطوّرين تسجيل القيمة المرجَعة من طرق الرسم وتمريرها إلى element.style.transform. تعرض الطريقة drawElementImage() الآن قيمة فارغة، وتعتمد المزامنة على السياق.
سياقات ثنائية الأبعاد: المزامنة التلقائية
في لوحة الرسم الثنائية الأبعاد، يزامن المتصفّح تلقائيًا حدود اختبار الضغط في نموذج العناصر في المستند (DOM) وحلقات التركيز الخاصة بقارئ الشاشة مع الإحداثيات المرسومة. يمكنك إزالة كل عمليات نقل البيانات التي تتضمّن تحويلاً يدويًا:
// 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
لإدارة الأشكال الهندسية يدويًا في ثنائي الأبعاد، مرِّر { preserveElementGeometry: true } إلى drawElementImage() وطبِّق عمليات التحويل باستخدام canvas.updateElementGeometry().
السياقات الثلاثية الأبعاد: فاضح updateElementGeometry()
لمزامنة DOM في سياقات WebGL أو WebGPU، أنشئ DOMMatrix تحويلاً
وامرّره إلى 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 });
});
التوافق مع الإصدارات المختلفة
إذا كان تطبيقك يجب أن يتيح للمستخدمين استخدام إصدارات متعددة من Chrome خلال الفترة الانتقالية، تحقَّق من توفّر الطرق المعدَّلة في النماذج الأولية وعدِّل عملية التنفيذ وفقًا لذلك.
تأكَّد من ضبط سمات عنصر <canvas> الصحيحة لكل إصدار من المتصفّح:
// ============================================================================
// 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', '');
}
}
بالنسبة إلى سياق ثنائي الأبعاد، افحص القيمة المعروضة من drawElementImage() وتحقّق من سمات نموذج لوحة الرسم المتوافق مع كلا الإصدارين:
// ============================================================================
// 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 = "";
}
}
}
بالنسبة إلى WebGPU، استخدِم توقيع الطريقة والاسم المتوافقَين:
// ============================================================================
// 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 });
}
}
احرص على التحقّق من توافق المتصفّح مع 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);
}
إضافة Origin Trial
تم تمديد مرحلة التجربة الأصلية لـ HTML-in-Canvas حتى الإصدار 160 من Chrome. احرص على تجديد الرمز المميّز لمرحلة التجربة والتقييم لمواصلة توفير ميزة HTML-in-Canvas للمستخدمين. لمزيد من التفاصيل، يُرجى الاطّلاع على مقالة "التجربة الأصلية".
مشاركة ملاحظاتك
يُرجى إعلامنا بكيفية عمل هذه التحديثات في تطبيقاتك من خلال إرسال مشكلة في مستودع WICG على GitHub. اشترِك في النشرة الإخبارية المخصصة للمطوّرين للبقاء على اطّلاع على آخر الأخبار المتعلقة بميزة "HTML في Canvas".