القرصنة CSS Animation State و Playback Time ذكاء بيانات PlatoBlockchain. البحث العمودي. عاي.

حالة الرسوم المتحركة للقرصنة ووقت التشغيل

ولفنشتاين CSS فقط هو مشروع صغير قمت بإنشائه قبل بضعة أسابيع. لقد كانت تجربة مع التحولات والرسوم المتحركة CSS ثلاثية الأبعاد.

مستوحاة من عرض FPS وآخر ولفنشتاين كودبين، قررت إنشاء نسختي الخاصة. يعتمد بشكل فضفاض على الحلقة 1 - الطابق 9 من لعبة Wolfenstein 3D الأصلية.

المحرر: تتطلب هذه اللعبة عن قصد بعض ردود الفعل السريعة لتجنب شاشة Game Over.

هذا فيديو playthrough:

[المحتوى جزءا لا يتجزأ]

باختصار ، ليس مشروعي سوى رسوم متحركة طويلة CSS مكتوبة بعناية. بالإضافة إلى حالات قليلة من الاختراق مربع الاختيار.

:checked ~ div { animation-name: spin; }

تتكون البيئة من وجوه شبكية ثلاثية الأبعاد والرسوم المتحركة في الغالب عبارة عن ترجمات وتدويرات ثلاثية الأبعاد بسيطة. لا شيء يتوهم حقا.

ومع ذلك ، كان حل مشكلتين صعبًا بشكل خاص:

  • قم بتشغيل الرسوم المتحركة "إطلاق السلاح" عندما ينقر اللاعب على عدو.
  • عندما حصل الزعيم سريع الحركة على الضربة الأخيرة ، أدخل حركة بطيئة مثيرة.

على المستوى الفني ، كان هذا يعني:

  • أعد تشغيل رسم متحرك عند تحديد خانة الاختيار التالية.
  • إبطاء الرسم المتحرك ، عند تحديد خانة اختيار.

في الواقع ، لم يتم حل أي منهما بشكل صحيح في مشروعي! إما انتهى بي الأمر باستخدام الحلول البديلة أو استسلمت للتو.

من ناحية أخرى ، بعد بعض البحث ، وجدت أخيرًا مفتاح كلتا المشكلتين: تغيير خصائص تشغيل الرسوم المتحركة لـ CSS. في هذه المقالة ، سوف نستكشف المزيد حول هذا الموضوع:

  • الكثير من الأمثلة التفاعلية.
  • التشريح: كيف يعمل كل مثال (أو لا يعمل)؟
  • خلف الكواليس: كيف تتعامل المتصفحات مع حالات الرسوم المتحركة؟

راقبني "ارموا لبناتي".

المشكلة 1: إعادة تشغيل الرسوم المتحركة

المثال الأول: "مجرد مربع اختيار آخر"

كان حدسي الأول هو "إضافة مربع اختيار آخر فقط" ، والذي لا يعمل:

يعمل كل مربع اختيار على حدة ، ولكن ليس كلاهما معًا. إذا تم تحديد أحد مربعات الاختيار بالفعل ، فلن يعمل الآخر.

إليك كيفية عمله (أو "لا يعمل"):

  1. animation-name of <div> is none بشكل افتراضي.
  2. ينقر المستخدم على مربع اختيار واحد ، animation-name يصبح spin، وتبدأ الرسوم المتحركة من البداية.
  3. بعد فترة ، ينقر المستخدم على مربع الاختيار الآخر. تسري قاعدة CSS الجديدة ، ولكن animation-name is لا يزال spin، مما يعني عدم إضافة أي رسوم متحركة أو إزالتها. تستمر الرسوم المتحركة ببساطة في اللعب كما لو لم يحدث شيء.

المثال الثاني: "استنساخ الرسوم المتحركة"

تتمثل إحدى طرق العمل في استنساخ الرسوم المتحركة:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2; }

هنا هو كيف يعمل:

  1. animation-name is none في البداية.
  2. ينقر المستخدم على "Spin!" ، animation-name يصبح spin1. الرسوم المتحركة spin1 بدأ من البداية لأنه تمت إضافته للتو.
  3. ينقر المستخدم على "Spin مرة أخرى!" ، animation-name يصبح spin2. الرسوم المتحركة spin2 بدأ من البداية لأنه تمت إضافته للتو.

لاحظ أنه في الخطوة رقم 3 ، spin1 تمت إزالته بسبب ترتيب قواعد CSS. لن تنجح إذا "تدور مرة أخرى!" يتم فحصه أولا.

المثال الثالث: "إلحاق نفس الرسم المتحرك"

نهج العمل الآخر هو "إلحاق نفس الرسوم المتحركة":

#spin1:checked ~ div { animation-name: spin; }
#spin2:checked ~ div { animation-name: spin, spin; }

هذا مشابه للمثال السابق. يمكنك بالفعل فهم السلوك بهذه الطريقة:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2, spin1; }

لاحظ أنه عند "Spin مرة أخرى!" تم تحديده ، تصبح الرسوم المتحركة القديمة هي الرسوم المتحركة الثانية في القائمة الجديدة ، والتي قد تكون غير بديهية. والنتيجة المباشرة هي: أن الحيلة لن تنجح إذا animation-fill-mode is forwards. هنا عرض توضيحي:

إذا كنت تتساءل عن سبب حدوث ذلك ، فإليك بعض الأدلة:

  • animation-fill-mode is none بشكل افتراضي ، مما يعني أن "الرسم المتحرك ليس له أي تأثير على الإطلاق إذا لم يتم تشغيله".
  • animation-fill-mode: forwards; تعني "بعد انتهاء تشغيل الرسم المتحرك ، يجب أن يظل في آخر إطار رئيسي إلى الأبد".
  • spin1قرار التجاوز دائمًا spin2لأن spin1 يظهر لاحقًا في القائمة.
  • لنفترض أن المستخدم نقر على "Spin!" ، وانتظر الدوران الكامل ، ثم نقر على "Spin مرة أخرى!". بهذه اللحظة. spin1 انتهى بالفعل ، و spin2 فقط يبدأ.

مناقشة

القاعدة العامة: لا يمكنك "إعادة تشغيل" رسم متحرك CSS موجود. بدلاً من ذلك ، تريد إضافة رسم متحرك جديد وتشغيله. قد يتم تأكيد ذلك بواسطة مواصفات W3C:

بمجرد أن يبدأ الرسم المتحرك يستمر حتى ينتهي أو يتم إزالة اسم الحركة.

الآن بمقارنة المثالين الأخيرين ، أعتقد أنه من الناحية العملية ، يجب أن تعمل "نسخ الرسوم المتحركة" بشكل أفضل ، خاصة عندما يكون معالج CSS المسبق متاحًا.

المشكلة الثانية: الحركة البطيئة

قد يعتقد المرء أن إبطاء الرسوم المتحركة هو مجرد مسألة تعيين لفترة أطول animation-duration:

div { animation-duration: 0.5s; }
#slowmo:checked ~ div { animation-duration: 1.5s; }

في الواقع ، هذا يعمل:

... أم هو كذلك؟

مع بعض التعديلات ، سيكون من الأسهل رؤية المشكلة.

نعم ، تم إبطاء الحركة. ولا ، لا تبدو جيدة. الكلب (تقريبًا) دائمًا "يقفز" عند تبديل مربع الاختيار. علاوة على ذلك ، يبدو أن الكلب يقفز إلى موضع عشوائي بدلاً من الموضع الأولي. كيف ذلك؟

سيكون من الأسهل فهمه إذا قدمنا ​​"عنصرين ظل":

يعمل كلا عنصري الظل على نفس الرسوم المتحركة مع اختلاف animation-duration. ولا يتأثرون بخانة الاختيار.

عندما تقوم بتبديل مربع الاختيار ، يقوم العنصر بالتبديل على الفور بين حالتي عنصري الظل.

نقلا عن مواصفات W3C:

يتم تطبيق التغييرات على قيم خصائص الرسوم المتحركة أثناء تشغيل الرسم المتحرك كما لو كان الرسم المتحرك يحتوي على هذه القيم منذ بدايته.

هذا يتبع عديم الجنسية التصميم ، والذي يسمح للمتصفحات بتحديد القيمة المتحركة بسهولة. تم وصف الحساب الفعلي هنا و هنا.

محاولة أخرى

تتمثل إحدى الأفكار في إيقاف الرسم المتحرك الحالي مؤقتًا ، ثم إضافة رسم متحرك أبطأ يبدأ من هناك:

div {
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

لذلك فهو يعمل:

... أم هو كذلك؟

إنها تبطئ عندما تنقر على "Slowmo!". ولكن إذا انتظرت دائرة كاملة ، فسترى "قفزة". في الواقع ، دائمًا ما يقفز إلى الموضع عند "Slowmo!" تم النقر فوقها.

السبب هو أننا لا نملك ملف from تم تعريف keyframe - ولا ينبغي لنا ذلك. عندما ينقر المستخدم على "Slowmo!" ، spin1 متوقف مؤقتًا في موضع ما ، و spin2 يبدأ في نفس الموقف بالضبط. لا يمكننا ببساطة التنبؤ بهذا الموقف مسبقًا ... أو هل يمكننا ذلك؟

حل عملي

نحن نقدر! باستخدام خاصية مخصصة ، يمكننا التقاط الزاوية في الرسم المتحرك الأول ، ثم تمريرها إلى الرسم المتحرك الثاني:

div {
  transform: rotate(var(--angle1));
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  transform: rotate(var(--angle2));
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

@keyframes spin1 {
  to {
    --angle1: 360deg;
  }
}

@keyframes spin2 {
  from {
    --angle2: var(--angle1);
  }
  to {
    --angle2: calc(var(--angle1) + 360deg);
  }
}

ملحوظة: @property يستخدم في هذا المثال ، وهو غير مدعوم من قبل جميع المتصفحات.

الحل "المثالي"

هناك تحذير للحل السابق: "الخروج من الوضع البطيء" لا يعمل بشكل جيد.

هنا حل أفضل:

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

يعمل هذا الحل مثل "تبديل" "التروس":

  • التروس: هناك نوعان <div>س. أحدهما والد الآخر. كلاهما لهما spin الرسوم المتحركة ولكن مع مختلف animation-duration. الحالة النهائية للعنصر هي تراكم كلتا الحركتين.
  • التحول: في البداية ، واحد فقط <div> لديها الرسوم المتحركة قيد التشغيل. الآخر متوقف مؤقتًا. عند تبديل مربع الاختيار ، تتبادل كلتا الحركتين حالتهما.

بينما تعجبني النتيجة حقًا ، إلا أن هناك مشكلة واحدة: إنها استغلال رائع لـ spin الرسوم المتحركة ، والتي لا تعمل مع أنواع الرسوم المتحركة الأخرى بشكل عام.

حل عملي (مع JS)

بالنسبة إلى الرسوم المتحركة العامة ، من الممكن تحقيق وظيفة الحركة البطيئة باستخدام القليل من JavaScript:

شرح سريع:

  • يتم استخدام خاصية مخصصة لتتبع تقدم الحركة.
  • يتم "إعادة تشغيل" الرسم المتحرك عند تبديل مربع الاختيار.
  • كود JS يحسب الصحيح animation-delay لضمان انتقال سلس. انصح هذا المقال إذا لم تكن معتادًا على القيم السلبية لـ animation-delay.

يمكنك عرض هذا الحل على أنه مزيج من نهج "إعادة تشغيل الرسوم المتحركة" ونهج "تبديل التروس".

من المهم هنا تتبع تقدم الرسوم المتحركة بشكل صحيح. الحلول ممكنة إذا @property غير متاح. كمثال ، يستخدم هذا الإصدار z-index لتتبع التقدم:

ملاحظة جانبية: في الأصل ، حاولت أيضًا إنشاء إصدار CSS فقط لكنني لم أنجح. بينما لست متأكدًا بنسبة 100٪ ، أعتقد أن السبب هو ذلك animation-delay is غير متحرك.

هنا نسخة مع الحد الأدنى من JavaScript. يعمل فقط "دخول بطيئة".

يرجى إعلامي إذا تمكنت من إنشاء إصدار CSS فعال فقط!

حركة بطيئة لأي رسوم متحركة (مع JS)

أخيرًا ، أود مشاركة حل يصلح (تقريبًا) لأي رسوم متحركة ، حتى مع التعقيدات المتعددة @keyframes:

في الأساس ، تحتاج إلى إضافة متتبع تقدم الرسوم المتحركة ، ثم الحساب بعناية animation-delay للرسوم المتحركة الجديدة. ومع ذلك ، قد يكون من الصعب أحيانًا (لكن ممكن) الحصول على القيم الصحيحة.

فمثلا:

  • animation-timing-function ليس linear.
  • animation-direction ليس normal.
  • قيم متعددة في animation-name مع مختلف animation-duration's و animation-delayالصورة.

هذه الطريقة موصوفة ايضا هنا ل واجهة برمجة تطبيقات الويب المتحركة.

شكر وتقدير

لقد بدأت السير في هذا المسار بعد مواجهة مشاريع CSS فقط. كان بعض عمل فني دقيق، وكان البعض بدع معقدة. المفضلة هي تلك التي تتضمن كائنات ثلاثية الأبعاد ، على سبيل المثال ، هذا كذاب الكرة وهذا مكعب التعبئة.

في البداية ، لم يكن لدي أدنى فكرة عن كيفية صنعها. قرأت فيما بعد وتعلمت الكثير منها هذا البرنامج التعليمي الجميل من قبل آنا تيودور.

كما اتضح ، لا يختلف بناء وتحريك كائنات ثلاثية الأبعاد باستخدام CSS كثيرًا عن القيام بذلك باستخدام خلاط ، فقط بنكهة مختلفة قليلاً.

وفي الختام

في هذه المقالة ، درسنا سلوك الرسوم المتحركة لـ CSS عندما يكون ملف animate-* تم تغيير الممتلكات. لقد توصلنا بشكل خاص إلى حلول لـ "إعادة تشغيل الرسوم المتحركة" و "الحركة البطيئة للرسوم المتحركة".

آمل أن تجد هذا المقال ممتعًا. أخبرني بأفكارك إذا سمحت!

الطابع الزمني:

اكثر من الخدع المغلق