Canvas هي طريقة شائعة لرسم جميع أنواع الرسومات على الشاشة ونقطة دخول إلى عالم WebGL. ويمكن استخدامها لرسم أشكال أو صور أو تشغيل صور متحركة أو حتى عرض محتوى الفيديو ومعالجته. ويتم استخدامه غالبًا لتوفير تجارب رائعة للمستخدمين في تطبيقات الويب الغنية بالوسائط والألعاب على الإنترنت.
ويمكن إنشاء المحتوى المرسوم على اللوحة بطريقة آلية، مثلاً باستخدام JavaScript. ويمنح ذلك مساحة العرض مرونة كبيرة.
في الوقت نفسه، في المواقع الإلكترونية الحديثة، يُعدّ تنفيذ النصوص البرمجية أحد أكثر مصادر مشاكل استجابة المستخدم شيوعًا. بما أنّ منطق اللوحة وعرضها يتمّان في سلسلة المهام نفسها التي يتفاعل معها المستخدم، يمكن أن تضرّ العمليات الحسابية (الثقيلة أحيانًا) المضمّنة في الرسومات المتحركة بالأداء المرئي والحقيقي للتطبيق.
لحسن الحظ، OffscreenCanvas هو ردّ على هذا التهديد.
في السابق، كانت إمكانات رسم اللوحة مرتبطة بعنصر <canvas>
،
ما يعني أنّها كانت تعتمد مباشرةً على DOM. كما يشير الاسم، يؤدي OffscreenCanvas إلى
فصل DOM عن واجهة برمجة التطبيقات Canvas من خلال نقله خارج الشاشة.
وبفضل هذا الفصل، يتم فصل عرض OffscreenCanvas بالكامل عن نموذج DOM، وبالتالي يقدّم بعض التحسينات على السرعة مقارنةً باللوحة العادية بسبب عدم وجود مزامنة بينهما.
بالإضافة إلى ذلك، يمكن استخدامها في Web Worker، حتى في حال عدم توفّر DOM. يتيح ذلك جميع أنواع حالات الاستخدام المثيرة للاهتمام.
استخدام OffscreenCanvas في Worker
Workers هي نسخة الويب من سلاسل المهام، وهي تتيح لك تنفيذ المهام في الخلفية.
يؤدي نقل بعض النصوص البرمجية إلى أحد خيوط العمل إلى منح تطبيقك مساحة أكبر لتنفيذ المهام المُهمّة للمستخدمين في الخيط الرئيسي. بدون OffscreenCanvas، لم تكن هناك طريقة لاستخدام واجهة برمجة التطبيقات Canvas API في أحد مهام Worker، لأنّه لم يكن هناك عنصر DOM متاحًا.
لا يعتمد OffscreenCanvas على نموذج DOM، لذا يمكن استخدامه. يستخدِم المثال التالي OffscreenCanvas لاحتساب لون متدرّج في عامل:
// file: worker.js
function getGradientColor(percent) {
const canvas = new OffscreenCanvas(100, 1);
const ctx = canvas.getContext('2d');
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'blue');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, ctx.canvas.width, 1);
const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}
getGradientColor(40); // rgba(152, 0, 104, 255 )
إزالة حظر سلسلة التعليمات الرئيسية
يتيح لك نقل العمليات الحسابية المكثفة إلى عامل تحرير موارد مهمة في سلسلة المهام الرئيسية. استخدِم الأسلوب transferControlToOffscreen لمطابقة اللوحة العادية مع مثيل OffscreenCanvas. سيتم عرض العمليات المطبَّقة على canvas Offscreen على لوحة الرسم المصدر تلقائيًا.
const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);
في المثال التالي، تحدث العملية الحسابية المكثّفة عند تغيير مظهر الألوان، ومن المفترض أن تأخذ بضع مللي ثوانٍ حتى على جهاز كمبيوتر مكتبي سريع. يمكنك اختيار تشغيل الصور المتحركة في سلسلة المهام الرئيسية أو في سلسلة المهام العاملة. في حال سلسلة التعليمات الرئيسية، لا يمكنك التفاعل مع الزر أثناء تنفيذ مهمة الصعوبة العالية، لأنّه يتم حظر سلسلة التعليمات. في حال العامل، لا يكون هناك أي تأثير على استجابة واجهة المستخدم.
وينطبق ذلك أيضًا على العكس: لا تؤثّر سلسلة التعليمات الرئيسية المشغولة في الحركة التي يتم تشغيلها على أحد خيوط العمل. يمكنك استخدام هذه الميزة لتجنّب الارتباك المرئي وضمان عرض حركة سلسة بالرغم من عدد عمليات المعالجة في سلسلة المهام الرئيسية، كما هو موضّح في العرض التجريبي التالي.
في حال استخدام لوحة عادية، يتوقف عرض الرسوم المتحركة عندما تصبح سلسلة المحادثات الرئيسية مشغولة بشكل مصطنع، في حين يتم تشغيل OffscreenCanvas المستند إلى Worker بسلاسة.
الاستخدام مع المكتبات الشائعة
بما أنّ واجهة برمجة التطبيقات OffscreenCanvas متوافقة بشكل عام مع عنصر Canvas العادي، يمكنك استخدامها كميزة تحسين تدريجي، بالإضافة إلى بعض مكتبات الرسومات الرائدة في السوق.
على سبيل المثال، يمكنك رصده باستخدام ميزة "الاستكشاف بالاستناد إلى العناصر" واستخدامه مع Three.js إذا كان متاحًا، وذلك من خلال تحديد خيار canvas في طريقة وضع تصميم أداة التقديم:
const canvasEl = document.querySelector('canvas');
const canvas =
'OffscreenCanvas' in window
? canvasEl.transferControlToOffscreen()
: canvasEl;
canvas.style = {width: 0, height: 0};
const renderer = new THREE.WebGLRenderer({canvas: canvas});
يُرجى العِلم أنّ مكتبة Three.js تتوقع أن تحتوي لوحة الرسم على سمتَي style.width
وstyle.height
.
لا يتضمّن OffscreenCanvas هذه السمة، لأنّه غير مرتبط بـ DOM، لذا عليك تقديمها بنفسك،
إما عن طريق استبدالها أو تقديم منطق يربط هذه القيم بسمات canvas الأصلية.
يوضّح ما يلي كيفية تشغيل صورة متحركة أساسية من Three.js في عامل:
تجدر الإشارة إلى أنّ بعض واجهات برمجة التطبيقات ذات الصلة بـ DOM غير متاحة بسهولة في Worker، لذا إذا أردت استخدام ميزات Three.js الأكثر تقدمًا، مثل النسيج، قد تحتاج إلى المزيد من الحلول البديلة. للحصول على بعض الأفكار حول كيفية بدء تجربة هذه الميزات، يمكنك الاطّلاع على الفيديو من مؤتمر Google I/O لعام 2017.
إذا كنت تستخدم بشكل كبير الإمكانات الرسومية للوحة، يمكن أن يؤثر OffscreenCanvas بشكلٍ positif في أداء تطبيقك. إنّ إتاحة سياقات عرض اللوحة للعمال يزيد من التوازي في تطبيقات الويب ويُحسِّن من استخدام الأنظمة المزوّدة بمعالجات متعددة النوى.