सीएसएस-ओनली वोल्फेंस्टीन एक छोटा सा प्रोजेक्ट है जिसे मैंने कुछ हफ्ते पहले बनाया था। यह CSS 3D ट्रांसफॉर्मेशन और एनिमेशन के साथ एक प्रयोग था।
से प्रेरित होकर एफपीएस डेमो और अन्य वोल्फेंस्टीन कोडपेन, मैंने अपना खुद का संस्करण बनाने का फैसला किया। यह मूल रूप से मूल वोल्फेंस्टीन 1 डी गेम के एपिसोड 9 - तल 3 पर आधारित है।
संपादक: गेम ओवर स्क्रीन से बचने के लिए इस गेम को जानबूझकर कुछ त्वरित प्रतिक्रिया की आवश्यकता है।
यहां एक प्लेथ्रू वीडियो है:
संक्षेप में, मेरी परियोजना और कुछ नहीं बल्कि एक सावधानीपूर्वक लिखी गई लंबी सीएसएस एनीमेशन है। प्लस के कुछ उदाहरण चेकबॉक्स हैक.
:checked ~ div { animation-name: spin; }
पर्यावरण में 3D ग्रिड चेहरे होते हैं और एनिमेशन ज्यादातर सादे 3D अनुवाद और घुमाव होते हैं। वास्तव में कुछ भी फैंसी नहीं है।
हालाँकि, दो समस्याओं को हल करना विशेष रूप से कठिन था:
- जब भी खिलाड़ी किसी दुश्मन पर क्लिक करता है तो "हथियार फायरिंग" एनीमेशन चलाएं।
- जब तेज़-तर्रार बॉस को आखिरी हिट मिली, तो एक नाटकीय धीमी गति दर्ज करें।
तकनीकी स्तर पर, इसका मतलब था:
- अगला चेकबॉक्स चेक किए जाने पर एनिमेशन फिर से चलाएं।
- जब एक चेकबॉक्स चेक किया जाता है, तो एनीमेशन को धीमा कर दें।
वास्तव में, मेरी परियोजना में न तो ठीक से हल किया गया था! मैंने या तो वर्कअराउंड का उपयोग करना समाप्त कर दिया या बस छोड़ दिया।
दूसरी ओर, कुछ खुदाई के बाद, अंततः मुझे दोनों समस्याओं की कुंजी मिल गई: सीएसएस एनिमेशन चलाने के गुणों को बदलना। इस लेख में, हम इस विषय पर आगे की खोज करेंगे:
- बहुत सारे इंटरैक्टिव उदाहरण।
- विच्छेदन: प्रत्येक उदाहरण कैसे काम करता है (या काम नहीं करता)?
- दृश्य के पीछे: ब्राउज़र एनीमेशन राज्यों को कैसे संभालते हैं?
मुझे करने दो "मेरी ईंटें फेंक दो".
समस्या 1: एनिमेशन को फिर से चलाना
पहला उदाहरण: "बस एक और चेकबॉक्स"
मेरा पहला अंतर्ज्ञान था "बस एक और चेकबॉक्स जोड़ें", जो काम नहीं करता है:
प्रत्येक चेकबॉक्स व्यक्तिगत रूप से काम करता है, लेकिन दोनों एक साथ नहीं। यदि एक चेकबॉक्स पहले से ही चेक किया गया है, तो दूसरा अब काम नहीं करता है।
यहां बताया गया है कि यह कैसे काम करता है (या "काम नहीं करता"):
- RSI
animation-name
of<div>
isnone
डिफ़ॉल्ट रूप से - उपयोगकर्ता एक चेकबॉक्स पर क्लिक करता है,
animation-name
हो जाता हैspin
, और एनीमेशन शुरुआत से शुरू होता है। - थोड़ी देर बाद, उपयोगकर्ता दूसरे चेकबॉक्स पर क्लिक करता है। एक नया CSS नियम प्रभावी होता है, लेकिन
animation-name
is अभी भीspin
, जिसका अर्थ है कि कोई एनीमेशन नहीं जोड़ा गया है और न ही हटाया गया है। एनीमेशन बस खेलना जारी रखता है जैसे कि कुछ हुआ ही नहीं।
दूसरा उदाहरण: "एनीमेशन क्लोनिंग"
एक काम करने का तरीका एनीमेशन को क्लोन करना है:
#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2; }
यहाँ है कि यह कैसे काम करता है:
animation-name
isnone
शुरू में।- उपयोगकर्ता "स्पिन!" पर क्लिक करता है,
animation-name
हो जाता हैspin1
. एनीमेशनspin1
शुरुआत से शुरू किया गया है क्योंकि इसे अभी जोड़ा गया था। - उपयोगकर्ता "फिर से स्पिन करें!" पर क्लिक करता है,
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
isnone
डिफ़ॉल्ट रूप से, जिसका अर्थ है "यदि नहीं चल रहा है तो एनीमेशन का कोई प्रभाव नहीं पड़ता है"।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-*
संपत्ति बदल दी जाती है। विशेष रूप से हमने "एनीमेशन को फिर से चलाने" और "एनीमेशन स्लो-मो" के समाधान के लिए काम किया।
मुझे आशा है कि आपको यह लेख रोचक लगा होगा। कृपया मुझे अपने विचारों से अवगत कराएं!