عرض وقت الاستجابة البطيء مع تلميح غير متزامن

Joe Medley
Joe Medley

الاختلافات في عرض قلم الشاشة

لطالما كانت تطبيقات الرسم المستندة إلى قلم الشاشة والمصممة للويب، تعاني من مشاكل زمن الانتقال لأنّ صفحة الويب يجب أن تزامن تحديثات الرسومات مع نموذج كائن المستند (DOM). في أي تطبيق رسم، يمكن أن تؤثر زمن الاستجابة التي تزيد عن 50 مللي ثانية في التنسيق بين اليد والعين لدى المستخدم، ما يجعل استخدام التطبيقات صعبًا.

يستدعي تلميح desynchronized لـ canvas.getContext() مسار رمز مختلفًا يتجاوز آلية تحديث DOM المعتادة. بدلاً من ذلك، يطلب التلميح من النظام الأساسي تخطي أكبر قدر ممكن من التركيب، وفي بعض الحالات، يتم إرسال المخزن المؤقت الأساسي للوحة الرسم مباشرةً إلى وحدة التحكم في شاشة الشاشة. يؤدي ذلك إلى إزالة وقت الاستجابة الذي قد يكون سبب استخدام قائمة انتظار مكوّن العارض.

ما مدى جودة المُنتَج؟

عرض "سينتل" في الوقت نفسه

للوصول إلى الرمز، انتقِل للأسفل. لرؤيته أثناء العمل، تحتاج إلى جهاز بشاشة تعمل باللمس، ويفضل قلم شاشة. (الأصابع مناسبة أيضًا). إذا كان لديك نموذج، جرّب نموذجَي 2d أو webgl. ولبقيةكم، يمكنكم الاطّلاع على هذا العرض التوضيحي الذي أعدّه "ميغيل كاساس"، وهو أحد المهندسين الذين نفّذوا هذه الميزة. افتح العرض التوضيحي، واضغط على تشغيل، ثم حرك شريط التمرير ذهابًا وإيابًا بشكل عشوائي وسريع.

يستخدم هذا المثال مقطعًا مدته دقيقة واحدة وواحد وعشرين ثانية من الفيلم القصير Sintel لـ "دوريان"، وهو مشروع الفيلم المفتوح Blender. في هذا المثال، يتم تشغيل الفيلم في عنصر <video> يتم عرض محتواه في الوقت نفسه على عنصر <canvas>. بإمكان العديد من الأجهزة تنفيذ ذلك بدون تمزيق، على الرغم من أنّ الأجهزة ذات العرض الأمامي، مثل ChromeOS، قد تحدث تمزّقًا. (الفيلم رائع ولكنه حزين. كنت عديم الفائدة لمدة ساعة بعد أن رأيته. اعتبر نفسك تحذيرًا.)

استخدام التلميح

إنّ إضافة وقت الاستجابة السريع هي أكثر فائدة من إضافة desynchronized إلى canvas.getContext(). سوف أستعرض المشكلات واحدة تلو الأخرى.

إنشاء اللوحة

وفي واجهة برمجة تطبيقات أخرى، سأناقش أولاً اكتشاف الميزات. بالنسبة إلى تلميح desynchronized، يجب عليك إنشاء اللوحة أولاً. استدعِ canvas.getContext() واضبط له تلميح desynchronized الجديد بقيمة true.

const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
  desynchronized: true,
  // Other options. See below.
});

رصد الميزات

بعد ذلك، اتّصِل بـ getContextAttributes(). إذا كان كائن السمات التي تم عرضها يحتوي على السمة desynchronized، عليك اختباره.

if (ctx.getContextAttributes().desynchronized) {
  console.log('Low latency canvas supported. Yay!');
} else {
  console.log('Low latency canvas not supported. Boo!');
}

تجنُّب الوميض

هناك حالتان يمكن أن تتسبب في حدوث وميض إذا لم يتم الترميز بشكل صحيح.

تقوم بعض المتصفحات بما في ذلك Chrome بمحو لوحات WebGL بين الإطارات. من الممكن أن تقرأ وحدة التحكم في العرض المخزن المؤقت عندما يكون فارغًا، ما يؤدي إلى وميض الصورة. ولتجنّب ذلك، عليك ضبط preserveDrawingBuffer على true.

const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
  desynchronized: true,
  preserveDrawingBuffer: true
});

يمكن أن يحدث الوميض أيضًا عند محو سياق الشاشة في رمز الرسم الخاص بك. وإذا كان عليك المحو، ارسم إلى المخزن المؤقت للإطارات خارج الشاشة، ثم انسخه إلى الشاشة.

قنوات الإصدار الأولي

لا يزال من الممكن إلغاء مزامنة عنصر لوحة الرسم شبه الشفاف، الذي تم تعيين ألفا فيه على "صحيح"، ولكن يجب ألا يحتوي على أي عناصر DOM أخرى فوقه.

يمكن أن يكون هناك واحد فقط

لا يمكنك تغيير سمات السياق بعد طلب الاستدعاء الأول إلى canvas.getContext(). كان هذا صحيحًا دائمًا، لكن تكراره قد يوفر عليك بعض الاستياء إذا لم تكن على دراية أو نسيت .

على سبيل المثال، لنفترض أنني حصلت على سياق وقمت بتحديد ألفا على أنها false، ثم استدعيت في وقت لاحق من التعليمة البرمجية canvas.getContext() مرة ثانية مع ضبط ألفا على true كما هو موضح أدناه.

const canvas = document.querySelector('myCanvas');
const ctx1 = canvas.getContext('2d', {
  alpha: false,
  desynchronized: true,
});

//Some time later, in another corner of code.
const ctx2 = canvas.getContext('2d', {
  alpha: true,
  desynchronized: true,
});

ليس من الواضح أنّ ctx1 وctx2 هما نفس الكائن. لا يزال ألفا خاطئًا ولا يتم إنشاء سياق به ألفا يساوي صوابًا.

أنواع اللوحات المتوافقة

المعلمة الأولى التي تم تمريرها إلى getContext() هي contextType. إذا كانت لديك معلومات سابقة بـ getContext()، لا شك في أنّك تتساءل عمّا إذا كان هناك أي معلومات أخرى متاحة، غير أنواع السياق '2d'. يعرض الجدول أدناه أنواع السياقات التي تتوافق مع السمة desynchronized.

contextType كائن نوع السياق

'2d'

CanvasRenderingContext2D

'webgl'

WebGLRenderingContext

'webgl2'

WebGL2RenderingContext

الخلاصة

إذا كنت تريد مشاهدة المزيد من هذا المحتوى، يمكنك الاطّلاع على النماذج. بالإضافة إلى مثال الفيديو الذي سبق وصفه، هناك أمثلة تعرض سياقي '2d' و"webgl".