हैकिंग CSS एनिमेशन स्टेट और प्लेबैक टाइम प्लेटोब्लॉकचैन डेटा इंटेलिजेंस। लंबवत खोज। ऐ.

हैकिंग CSS एनिमेशन स्टेट और प्लेबैक टाइम

सीएसएस-ओनली वोल्फेंस्टीन एक छोटा सा प्रोजेक्ट है जिसे मैंने कुछ हफ्ते पहले बनाया था। यह CSS 3D ट्रांसफॉर्मेशन और एनिमेशन के साथ एक प्रयोग था।

से प्रेरित होकर एफपीएस डेमो और अन्य वोल्फेंस्टीन कोडपेन, मैंने अपना खुद का संस्करण बनाने का फैसला किया। यह मूल रूप से मूल वोल्फेंस्टीन 1 डी गेम के एपिसोड 9 - तल 3 पर आधारित है।

संपादक: गेम ओवर स्क्रीन से बचने के लिए इस गेम को जानबूझकर कुछ त्वरित प्रतिक्रिया की आवश्यकता है।

यहां एक प्लेथ्रू वीडियो है:

[एम्बेडेड सामग्री]

संक्षेप में, मेरी परियोजना और कुछ नहीं बल्कि एक सावधानीपूर्वक लिखी गई लंबी सीएसएस एनीमेशन है। प्लस के कुछ उदाहरण चेकबॉक्स हैक.

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

पर्यावरण में 3D ग्रिड चेहरे होते हैं और एनिमेशन ज्यादातर सादे 3D अनुवाद और घुमाव होते हैं। वास्तव में कुछ भी फैंसी नहीं है।

हालाँकि, दो समस्याओं को हल करना विशेष रूप से कठिन था:

  • जब भी खिलाड़ी किसी दुश्मन पर क्लिक करता है तो "हथियार फायरिंग" एनीमेशन चलाएं।
  • जब तेज़-तर्रार बॉस को आखिरी हिट मिली, तो एक नाटकीय धीमी गति दर्ज करें।

तकनीकी स्तर पर, इसका मतलब था:

  • अगला चेकबॉक्स चेक किए जाने पर एनिमेशन फिर से चलाएं।
  • जब एक चेकबॉक्स चेक किया जाता है, तो एनीमेशन को धीमा कर दें।

वास्तव में, मेरी परियोजना में न तो ठीक से हल किया गया था! मैंने या तो वर्कअराउंड का उपयोग करना समाप्त कर दिया या बस छोड़ दिया।

दूसरी ओर, कुछ खुदाई के बाद, अंततः मुझे दोनों समस्याओं की कुंजी मिल गई: सीएसएस एनिमेशन चलाने के गुणों को बदलना। इस लेख में, हम इस विषय पर आगे की खोज करेंगे:

  • बहुत सारे इंटरैक्टिव उदाहरण।
  • विच्छेदन: प्रत्येक उदाहरण कैसे काम करता है (या काम नहीं करता)?
  • दृश्य के पीछे: ब्राउज़र एनीमेशन राज्यों को कैसे संभालते हैं?

मुझे करने दो "मेरी ईंटें फेंक दो".

समस्या 1: एनिमेशन को फिर से चलाना

पहला उदाहरण: "बस एक और चेकबॉक्स"

मेरा पहला अंतर्ज्ञान था "बस एक और चेकबॉक्स जोड़ें", जो काम नहीं करता है:

प्रत्येक चेकबॉक्स व्यक्तिगत रूप से काम करता है, लेकिन दोनों एक साथ नहीं। यदि एक चेकबॉक्स पहले से ही चेक किया गया है, तो दूसरा अब काम नहीं करता है।

यहां बताया गया है कि यह कैसे काम करता है (या "काम नहीं करता"):

  1. RSI 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. उपयोगकर्ता "स्पिन!" पर क्लिक करता है, animation-name हो जाता है spin1. एनीमेशन spin1 शुरुआत से शुरू किया गया है क्योंकि इसे अभी जोड़ा गया था।
  3. उपयोगकर्ता "फिर से स्पिन करें!" पर क्लिक करता है, 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; }

ध्यान दें कि जब "फिर से स्पिन करें!" चेक किया जाता है, तो पुरानी चल रही एनीमेशन नई सूची में दूसरी एनीमेशन बन जाती है, जो अनपेक्षित हो सकती है। एक सीधा परिणाम यह है: ट्रिक काम नहीं करेगी अगर animation-fill-mode is forwards. यहाँ एक डेमो है:

अगर आपको आश्चर्य है कि ऐसा क्यों है, तो यहां कुछ सुराग दिए गए हैं:

  • animation-fill-mode is none डिफ़ॉल्ट रूप से, जिसका अर्थ है "यदि नहीं चल रहा है तो एनीमेशन का कोई प्रभाव नहीं पड़ता है"।
  • animation-fill-mode: forwards; इसका अर्थ है "एनीमेशन के चलने के बाद, इसे हमेशा के लिए अंतिम कीफ़्रेम पर रहना चाहिए"।
  • spin1का निर्णय हमेशा ओवरराइड करता है spin2क्योंकि है spin1 बाद में सूची में दिखाई देता है।
  • मान लीजिए कि उपयोगकर्ता "स्पिन!" पर क्लिक करता है, एक पूर्ण स्पिन की प्रतीक्षा करता है, फिर "फिर से स्पिन करें!" पर क्लिक करता है। इस पल। spin1 पहले ही समाप्त हो चुका है, और spin2 बस शुरू होता है।

चर्चा

अंगूठे का नियम: आप मौजूदा सीएसएस एनीमेशन को "पुनरारंभ" नहीं कर सकते। इसके बजाय, आप एक नया एनिमेशन जोड़ना और चलाना चाहते हैं। इसकी पुष्टि द्वारा की जा सकती है W3C विशिष्टता:

एक बार एनीमेशन शुरू हो जाने के बाद यह समाप्त होने तक या एनीमेशन-नाम हटा दिए जाने तक जारी रहता है।

अब पिछले दो उदाहरणों की तुलना करते हुए, मुझे लगता है कि व्यवहार में, "क्लोनिंग एनिमेशन" को अक्सर बेहतर काम करना चाहिए, खासकर जब सीएसएस प्रीप्रोसेसर उपलब्ध हो।

समस्या 2: धीमी गति

कोई सोच सकता है कि एनीमेशन को धीमा करना केवल एक लंबा सेट करने की बात है 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;
}

तो यह काम करता है:

... या करता है?

जब आप "स्लोमो!" पर क्लिक करते हैं तो यह धीमा हो जाता है। लेकिन अगर आप एक पूर्ण चक्र की प्रतीक्षा करते हैं, तो आप एक "कूद" देखेंगे। वास्तव में, यह हमेशा उस स्थिति में कूद जाता है जब "स्लोमो!" पर क्लिक किया जाता है।

कारण यह है कि हमारे पास नहीं है from कीफ्रेम परिभाषित - और हमें नहीं करना चाहिए। जब उपयोगकर्ता “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 एनीमेशन, जो सामान्य रूप से अन्य प्रकार के एनिमेशन के लिए काम नहीं करता है।

एक व्यावहारिक समाधान (जेएस के साथ)

सामान्य एनिमेशन के लिए, थोड़ी जावास्क्रिप्ट के साथ धीमी गति के कार्य को प्राप्त करना संभव है:

एक त्वरित स्पष्टीकरण:

  • एनीमेशन प्रगति को ट्रैक करने के लिए एक कस्टम प्रॉपर्टी का उपयोग किया जाता है।
  • जब चेकबॉक्स टॉगल किया जाता है तो एनीमेशन "पुनरारंभ" होता है।
  • जेएस कोड सही गणना करता है animation-delay एक निर्बाध संक्रमण सुनिश्चित करने के लिए। मेरा सुझाव है इस लेख यदि आप के ऋणात्मक मूल्यों से परिचित नहीं हैं animation-delay.

आप इस समाधान को "पुनरारंभ एनीमेशन" और "गियर-शिफ्टिंग" दृष्टिकोण के एक संकर के रूप में देख सकते हैं।

यहां एनीमेशन प्रगति को सही ढंग से ट्रैक करना महत्वपूर्ण है। समाधान संभव हैं यदि @property उपलब्ध नहीं है। एक उदाहरण के रूप में, यह संस्करण उपयोग करता है z-index प्रगति को ट्रैक करने के लिए:

साइड-नोट: मूल रूप से, मैंने केवल-सीएसएस संस्करण बनाने की भी कोशिश की, लेकिन सफल नहीं हुआ। जबकि 100% निश्चित नहीं है, मुझे लगता है कि ऐसा इसलिए है क्योंकि animation-delay is एनिमेटेबल नहीं.

यहां न्यूनतम जावास्क्रिप्ट वाला एक संस्करण है। केवल "धीमा में प्रवेश करना" काम करता है।

कृपया मुझे बताएं कि क्या आप एक कार्यशील CSS-केवल संस्करण बनाने का प्रबंधन करते हैं!

धीमी गति से कोई भी एनिमेशन (JS के साथ)

अंत में, मैं एक समाधान साझा करना चाहता हूं जो (लगभग) किसी भी एनीमेशन के लिए काम करता है, यहां तक ​​​​कि कई जटिल के साथ भी @keyframes:

मूल रूप से, आपको एक एनीमेशन प्रगति ट्रैकर जोड़ने की जरूरत है, फिर ध्यान से गणना करें animation-delay नए एनिमेशन के लिए। हालांकि, कभी-कभी सही मान प्राप्त करना मुश्किल (लेकिन संभव) हो सकता है।

उदाहरण के लिए:

  • animation-timing-function नहीं है linear.
  • animation-direction नहीं है normal.
  • में एकाधिक मान animation-name विभिन्न साथ animation-duration'रेत animation-delayएस

यह विधि भी वर्णित है यहाँ उत्पन्न करें के लिए वेब एनिमेशन एपीआई.

Acknowledgments

मैंने सीएसएस-ओनली प्रोजेक्ट्स का सामना करने के बाद इस रास्ते को शुरू किया। कुछ थे नाजुक कलाकृति, और कुछ थे जटिल गर्भनिरोधक. मेरे पसंदीदा वे हैं जिनमें 3D ऑब्जेक्ट शामिल हैं, उदाहरण के लिए, यह उछलती गेंद और इस पैकिंग क्यूब.

शुरुआत में, मुझे नहीं पता था कि ये कैसे बनते हैं। बाद में मैंने पढ़ा और बहुत कुछ सीखा एना ट्यूडर द्वारा यह अच्छा ट्यूटोरियल.

जैसा कि यह निकला, CSS के साथ 3D ऑब्जेक्ट बनाना और एनिमेट करना इसके साथ करने से बहुत अलग नहीं है ब्लेंडर, बस थोड़ा अलग स्वाद के साथ।

निष्कर्ष

इस लेख में हमने सीएसएस एनिमेशन के व्यवहार की जांच की जब एक animate-* संपत्ति बदल दी जाती है। विशेष रूप से हमने "एनीमेशन को फिर से चलाने" और "एनीमेशन स्लो-मो" के समाधान के लिए काम किया।

मुझे आशा है कि आपको यह लेख रोचक लगा होगा। कृपया मुझे अपने विचारों से अवगत कराएं!

समय टिकट:

से अधिक सीएसएस ट्रिक्स