واجهة HTML-in-Canvas: Chrome يرسم DOM حقيقيًا داخل canvas وWebGL
إن بنيت يومًا تطبيقًا على canvas فأنت تعرف تلك اللحظة: الرسوميات سريعة، ثم يسأل أحدهم لماذا لا يستطيع تحديد النص، أو البحث فيه بـCtrl+F، أو سماعه عبر قارئ الشاشة. واجهة HTML-in-Canvas في Chrome، المتاحة الآن كتجربة أولية (origin trial)، جواب عن هذا السؤال. فهي ترسم محتوى DOM حقيقيًا داخل canvas ثنائي الأبعاد أو خامة WebGL أو WebGPU، ويبقى المحتوى تفاعليًا ومتاحًا لتقنيات الوصول.
الاختيار الذي تلغيه
يصف Thomas Nattestad وNatalia Markoborodova الأمر بأنه مفاضلة قديمة. يمنحك DOM تخطيط النص وعناصر النماذج وكل ميزات المتصفح المبنية فوقه: أدوات الوصول، والترجمة، والبحث في الصفحة، ووضع القراءة، والإضافات، والتكبير، والملء التلقائي. أما canvas وWebGL وWebGPU فتمنحك شبكة من البكسلات وسرعة منخفضة المستوى، ولهذا تستخدمها الألعاب وتطبيقات مثل Google Docs وFigma. والثمن أن النص داخل شبكة البكسلات يفقد كل تلك الميزات، وإعادة بناء حتى النص المتجاوب يدويًا تكبّر حجم الحزمة.
ما الذي تحصل عليه
بحسب مقال Chrome، يحتفظ المحتوى المرسوم بهذه الطريقة بما يلي:
- تخطيط النص، بما فيه النص متعدد الأسطر وثنائي الاتجاه مع تطبيق CSS،
- عناصر نماذج حقيقية،
- تحديد النص والنسخ واللصق وقائمة النقر الأيمن،
- شجرة الوصول، فتقرؤه قارئات الشاشة كأي HTML عادي،
- البحث في الصفحة، مع إبراز النتيجة داخل خامة WebGL،
- الإضافات وأدوات المطور: غيّر قيمة CSS في المفتش فتتحدث الخامة ثلاثية الأبعاد.
سطر النص ثنائي الاتجاه يهمني تحديدًا. فالنص العربي الذي تتخلله كلمة إنجليزية من الأشياء التي تخطئ فيها تطبيقات canvas عادة، وهنا يتولى محرك النص في المتصفح نفسه هذا العمل.
كيف تعمل، في ثلاث خطوات
أولًا، ضع HTML داخل عنصر <canvas> وأضف السمة layoutsubtree، التي تطلب من المتصفح تخطيط هذا المحتوى وكشفه لشجرة الوصول. ثانيًا، ارسمه داخل حدث paint الخاص بالـcanvas، وهو يُطلق كلما احتاج العنصر إلى إعادة رسم، كما عند تحديد النص أو الكتابة. ثالثًا، طبّق التحويل الذي يعيده استدعاء الرسم على style.transform للعنصر، لتقع النقرات ومرور المؤشر حيث رُسم العنصر فعلًا. هذا هو مثال المقال ثنائي الأبعاد:
<canvas id="canvas" style="width: 200px; height: 200px;" layoutsubtree>
<div id="form_element">
<label for="name">Name:</label> <input id="name" type="text">
</div>
</canvas>
const ctx = document.getElementById('canvas').getContext('2d');
const form_element = document.getElementById('form_element');
const canvas = document.getElementById('canvas');
canvas.onpaint = () => {
ctx.reset();
// Draw the form element at x:0, y:0
let transform = ctx.drawElementImage(form_element, 0, 0);
// Sync the DOM location with the drawn location
form_element.style.transform = transform.toString();
};
في WebGL الاستدعاء هو texElementImage2D، ويعمل مثل texImage2D لكنه يأخذ عنصر DOM. وفي WebGPU هو copyElementImageToTexture على طابور الجهاز. وفي المشاهد ثلاثية الأبعاد لا يستطيع المتصفح أن يعرف أين يضع الـshader الخامة، فتبني المصفوفة بنفسك وتمررها إلى getElementTransform(). لدى Three.js دعم تجريبي بالفعل عبر THREE.HTMLTexture، ولدى PlayCanvas دعم عبر واجهة الخامات الخاصة به، وهذا يوفر عليك حساب المصفوفات.
كيف تجربها، وما حدودها
يقول المقال إن الواجهة في تجربة أولية في Chrome من الإصدار 148 حتى 150، وإنها في مرحلة مبكرة وقد تتغير تفاصيلها. للتجربة محليًا استخدم Chrome Canary بإصدار 149 أو أحدث مع تفعيل العلم chrome://flags/#canvas-draw-element. ولتفعيلها لزوار موقعك، سجّل موقعك في التجربة الأولية.
يذكر الكاتبان قيدين. الأول أنها لا تعمل مع محتوى iframe من أصل مختلف، لأسباب أمنية وأسباب تتعلق بالخصوصية. والثاني أن المحتوى يُرسم بـJavaScript، فلا يمكن للتمرير والحركة داخل canvas أن يعملا بمعزل عن الخيط الرئيسي كما في الصفحة العادية، فتأنَّ قبل وضع قائمة طويلة قابلة للتمرير داخلها.
نصيحة عامة: هذه الواجهة للتطبيقات التي تعيش أصلًا داخل canvas. أما الصفحة العادية المبنية بـHTML وCSS فلديها كل هذه الميزات أصلًا، ولا تكسب شيئًا من الانتقال إليها.
الخطوة التالية: ثبّت Chrome Canary، وفعّل العلم، وجرّب المثال ثنائي الأبعاد أعلاه بحقل من نماذجك. إن صمد، فسجّل في التجربة واحتفظ ببديل لكل المتصفحات الأخرى. المصدر: مدونة Chrome for Developers: تقديم التجربة الأولية لواجهة HTML-in-Canvas.
ملاحظات القراء