تحريك تمويه

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

TL;DR

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

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

المشكلة

تحوّل وحدة المعالجة المركزية (CPU) العلامات إلى مواد. يتم تحميل النسيج إلى وحدة معالجة الرسومات. ترسم وحدة معالجة الرسومات
هذه النسيج إلى إطار التخزين المؤقت للصور باستخدام أدوات الإضاءة. يحدث التمويه في
مخطّط الألوان.

في الوقت الحالي، لا يمكننا جعل التمويه المتحرّك يعمل بكفاءة. ومع ذلك، يمكننا العثور على حل بديل يبدو جيدًا بما يكفي، ولكنّه من الناحية الفنية ليس مؤثرًا متحركة للتشويش. للبدء، لنفهم أولاً سبب بطء التمويه المتحرك. لتمويه العناصر على الويب، هناك طريقتان: سمة filter في CSS وفلاتر SVG. ونظرًا لزيادة مدى توفّر فلاتر CSS وسهولة استخدامها، يتم استخدامها عادةً. إذا كان عليك توفير إمكانية استخدام Internet Explorer، ليس لديك خيار سوى استخدام فلاتر SVG لأنّ الإصدارَين 10 و11 من IE يتيحان استخدامها ولكن ليس فلاتر CSS. والخبر السارّ هو أنّ الحلّ البديل الذي نقدّمه لإضافة تأثير التمويه إلى الصورة يعمل مع كلتا الطريقتَين. لنحاول العثور على نقطة التوقف من خلال الاطّلاع على DevTools.

في حال تفعيل ميزة "وميض الطلاء" في "أدوات مطوّري البرامج"، لن تظهر لك أي ومضات على الإطلاق. يبدو أنّه لم يتم إجراء أي عمليات إعادة طلاء. وهذا صحيح من الناحية الفنية لأنّ "إعادة الطلاء" تشير إلى أنّ وحدة المعالجة المركزية (CPU) يجب أن تعيد طلاء نسيج العنصر الذي تمت ترقيته. عندما يتم ترقية عنصر وتمويهه، تطبّق وحدة معالجة الرسومات التمويه باستخدام برنامج تشويش.

تستخدم فلاتر SVG وفلاتر CSS فلاتر التفاف لتطبيق أثر التمويه. فلاتر التفاف هي عمليات باهظة التكلفة إلى حدٍ ما، لأنّه يجب مراعاة عدد من وحدات البكسل المُدخلة لكل وحدة بكسل ناتجة. وكلما كانت الصورة أكبر أو زاد نصف قطر التمويه، زادت تكلفة التأثير.

وهنا تكمن المشكلة، فنحن نُجري عملية GPU مكلفة إلى حدٍ ما في كل لقطة، ما يؤدي إلى تجاوز ميزانية اللقطة التي تبلغ 16 ملي ثانية، وبالتالي ينتهي بنا الأمر بمعدل أقل بكثير من 60 لقطة في الثانية.

رحلة في متاهة الأرانب

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

التمويه المتداخل هو سلسلة من عمليات التمويه المتداخلة التي تزيد من مستوى الشفافية أو تقلّله. على سبيل المثال، إذا كانت لدينا أربع مراحل تمويه، يمكننا إخفاء المرحلة الأولى وإظهار المرحلة الثانية في الوقت نفسه. بعد أن تصل المرحلة الثانية إلى مستوى شفافية% 100 وتصل المرحلة الأولى إلى مستوى شفافية %0، يتم إخفاء المرحلة الثانية وإظهار المرحلة الثالثة. بعد الانتهاء من ذلك، نزيل تدريجيًا المرحلة الثالثة ونزيل النسخة الرابعة والأخيرة. في هذا السيناريو، ستستغرق كل مرحلة ¼ من إجمالي المدة المطلوبة. من الناحية المرئية، يبدو هذا مشابهًا جدًا لتأثير التمويه المتحرك الحقييقي.

في تجاربنا، أدّت زيادة نصف قطر التمويه بشكلٍ أسي لكل مرحلة إلى تحقيق أفضل النتائج المرئية. مثال: إذا كانت لدينا أربع مراحل تمويه، سنطبّق filter: blur(2^n) على كل مرحلة، أي المرحلة 0: 1 بكسل، والمرحلة 1: 2 بكسل، والمرحلة 2: 4 بكسل والمرحلة 3: 8 بكسل. إذا فرضنا كل نسخة من هذه النُسخ المموّهة على طبقتها الخاصة (يُشار إليها باسم "الترويج") باستخدام will-change: transform، من المفترض أن يكون تغيير مستوى الشفافية في هذه العناصر سريعًا جدًا. من الناحية النظرية، سيتيح لنا ذلك التركيز على العمل المكلف المتعلق التمويه. تبيّن أنّ المنطق غير سليم. إذا شغّلت هذه النسخة التجريبية، ستلاحظ أنّ معدّل عرض اللقطات لا يزال أقل من 60 لقطة في الثانية، وأنّ التمويه أصبح أسوأ مما كان عليه من قبل.

أدوات المطوّر
  تعرض تتبعًا يُظهر أنّ وحدة معالجة الرسومات كانت مشغولة لفترات طويلة.

من خلال إلقاء نظرة سريعة على DevTools، تبيّن أنّ وحدة معالجة الرسومات لا تزال مشغولة للغاية وتعمل على تمديد كل لقطة إلى 90 ملي ثانية تقريبًا. ولكن لماذا؟ لم نعد نغيّر قيمة التمويه ، بل نغيّر مستوى الشفافية فقط. ما الذي يحدث؟ تكمن المشكلة مرة أخرى في طبيعة تأثير التمويه: كما أوضحنا سابقًا، إذا كان العنصر مميّزًا ومموّهًا في الوقت نفسه، يطبّق وحدة المعالجة الرسومية التأثير. وبالتالي، على الرغم من أنّنا لم نعُد نضيف تأثيرًا متحركًا على قيمة التمويه، يبقى النسيج نفسه غير مموّه ويتطلب إعادة التمويه في كل لقطة بواسطة وحدة معالجة الرسومات. يرجع سبب تفاقم معدل عرض اللقطات مقارنةً بسابق عهده إلى أنّ وحدة معالجة الرسومات تُجري في الواقع المزيد من العمل مقارنةً بسابق عهده، وذلك لأنّه في معظم الأوقات يظهر سمتان مرئيتان يجب تمويههما بشكل مستقل.

إنّ النتيجة التي توصلنا إليها ليست جميلة، ولكنها تجعل الرسوم المتحركة سريعة جدًا. نعود إلى عدم الترويج للعنصر الذي سيتم تمويهه، ولكن بدلاً من ذلك، نروّج لملف ملتفٍ رئيسي. إذا تم تمويه عنصر معيّن وتمت ترقيته، تطبّق وحدة معالجة الرسومات أثر التمويه. هذا هو السبب في بطء الإصدار التجريبي. إذا تم تمويه العنصر ولكن لم يتم ترقيته، يتم تحويل التمويه إلى شبكة بكسل على أقرب نسيج رئيسي بدلاً من ذلك. في هذه الحالة، يكون عنصر الغلاف الرئيسي الذي تمت ترقيته. أصبحت الصورة المموّهة الآن ملمس العنصر الرئيسي ويمكن إعادة استخدامها في جميع اللقطات المستقبلية. لا يعمل هذا الإجراء إلا لأنّنا نعلم أنّ العناصر المموّهة ليست متحركة، وتعدّ عملية تخزينها مؤقتًا مفيدة. في ما يلي عرض توضيحي لتنفيذ هذه التقنية. ما رأيك في استخدام هذا الأسلوب على هاتف Moto G4؟ تنبيه بكشف تفاصيل عن الحبكة: يعتقد الجهاز أنّه رائع:

DevTools
  تعرض تتبعًا يُظهر أنّ وحدة معالجة الرسومات لديها الكثير من وقت التوقف.

أصبح لدينا الآن الكثير من المساحة في وحدة معالجة الرسومات وسرعة سلسة تبلغ 60 لقطة في الثانية. لقد نجحنا.

طرح الإصدار العلني

في العرض التقديمي، نسخنا بنية DOM عدة مرات للحصول على نُسخ من المحتوى تم تمويهها بدرجات مختلفة. قد تتساءل عن كيفية عمل ذلك في بيئة الإنتاج، لأنّ ذلك قد يؤدي إلى بعض الآثار الجانبية غير المقصودة في أنماط CSS الخاصة بالمؤلف أو حتى JavaScript. أنت على حق. ننصحك باستخدام Shadow DOM.

على الرغم من أنّ معظم الأشخاص ينظرون إلى Shadow DOM على أنّه طريقة لإرفاق عناصر "داخلية" بالعناصر المخصّصة، إلا أنّه يُعدّ أيضًا عنصرًا أساسيًا لتحسين الأداء وتحقيق العزل. لا يمكن لـ JavaScript وCSS اختراق حدود Shadow DOM ، ما يتيح لنا تكرار المحتوى بدون التدخل في أنماط المطوّر أو منطق التطبيق. لدينا حاليًا عنصر <div> لكل نسخة من أجل تحويلها إلى صورة نقطية، ونستخدم الآن عناصر <div> هذه كمضيفين شبحيّين. ونُنشئShadowRoot باستخدامattachShadow({mode: 'closed'}) ونُرفِق نسخة منShadowRoot بدلاً من<div> نفسه. يجب أن نحرص أيضًا على نسخ جميع أوراق الأنماط إلى ShadowRoot لضمان أن يتم تنسيق النُسخ بالطريقة نفسها التي تم بها تنسيق الملف الأصلي.

لا تتوافق بعض المتصفّحات مع الإصدار 1 من Shadow DOM، لذلك نلجأ إلى تكرار المحتوى في هذه المتصفّحات ونأمل ألا يؤدي ذلك إلى حدوث أي مشاكل. كان بإمكاننا استخدام Shadow DOM polyfill مع ShadyCSS، ولكنّنا لم نفِّذ هذا في مكتبتنا.

بعد رحلة استكشافنا لمسار العرض في Chrome، توصّلنا إلى كيفية إضافة تأثير التمويه بشكل فعّال في جميع المتصفّحات.

الخاتمة

يجب عدم استخدام هذا النوع من التأثيرات بشكل عفوي. وبما أنّنا ننسخ عناصر DOM ونقوم بفرضها على طبقتها الخاصة، يمكننا تحسين أداء الأجهزة المنخفضة الأداء. إنّ نسخ جميع جداول الأنماط إلى كل ShadowRoot يشكّل بدوره خطرًا محتملاً على الأداء، لذا عليك تحديد ما إذا كنت تفضّل تعديل منطقك وأنماطك لكي لا تتأثر بنسخ الملفات في LightDOM أو استخدام أسلوب ShadowDOM. ولكن في بعض الأحيان، قد تكون أسلوبنا استثمارًا جديرًا بالاهتمام. يمكنك الاطّلاع على الرمز في مستودع GitHub، بالإضافة إلى العرض التجريبي، والتواصل معنا على Twitter إذا كانت لديك أي أسئلة.