समय-आधारित CSS animation तकनीक
(yuanchuan.dev)- CSS math functions का support बढ़ने के साथ, keyframes की जगह time tick variable
--tसे animation state calculate करने वाला तरीका फिर से व्यावहारिक हो गया है @property --tऔर86400000msलंबी root animation को मिलाने पर millisecond-level time बढ़ता है, और इसेrotate,translateजैसी properties की calculation से जोड़ा जा सकता हैstep()का उपयोग करके 8fps, 24fps, 60fps जैसे frame rate को सीमित किया जा सकता है, और browser optimization की वजह से 60fps से अधिक update frequency भी आमतौर पर समस्या नहीं बनतीmin(),mod(),sin(),pow(),round()से time values को limit, repeat, oscillate और ease करके keyframes के बिना custom easing और position movement व्यक्त किया जा सकता हैcss-doodle@t,@T,@TSजैसे shorthand expressions देता है, जिससे math-heavy demos को छोटा लिखना और तेजी से experiment करना आसान हो जाता है
time tick को CSS variable बनाना
- पहले CSS में complex math calculation करना कठिन था, इसलिए इस approach का scope सीमित था
- अब CSS
mod(),round(), trigonometric functions आदि जरूरी math functions support करता है, इसलिए time-based animations को फिर से आजमाया जा सकता है - Demo देखने के लिए Experimental feature flags enable करने की जरूरत हो सकती है
basic working model
- JavaScript की तरह CSS सीधे timer शुरू नहीं कर सकता, लेकिन CSS Houdini API से custom variable
--tdefine करके millisecond-level time track किया जा सकता है - basic example में
@property --tको<integer>के रूप में declare किया जाता है,@keyframes tickमें इसे0से86400000तक बदलाया जाता है, और:rootपर86400000ms linear infiniteanimation apply की जाती है --tहर 1 millisecond में1से बढ़ता है और 1 second में1000हो जाता हैcounter()का उपयोग करके current--tvalue को screen पर दिखाया जा सकता हैrotate: calc(var(--t) * .001turn)की तरह--t-based calculation को property से जोड़ने पर समय के साथ value बदलती है और यह animation बन जाती है
frame rate control
- smooth animation के लिए 60fps update frequency पर्याप्त है
- browser rendering optimization मौजूद है, इसलिए update frequency 60fps से अधिक होने पर भी आमतौर पर समस्या नहीं होती
- जरूरत पड़ने पर
animation-timing-functionमें step() का उपयोग करके frame rate को सीधे limit किया जा सकता है- 8fps:
step(calc(86400000/(1000/8))) - 24fps:
step(calc(86400000/(1000/24))) - 60fps:
step(calc(86400000/(1000/60)))
- 8fps:
बढ़ती time value को animation value में बदलना
--tvalue लगातार एक ही दिशा में बढ़ती रहती हैanglevalue360degसे आगे जाए तो भी ठीक है, लेकिन सभी CSS properties values को cyclic तरीके से handle नहीं करतींtranslate: calc(var(--t) * .001px)box को लगातार दाईं ओर move करता है-
min() से रोकना
- किसी खास offset पर पहुंचते ही रोकना हो तो min() का उपयोग किया जा सकता है
translate: min(270px, calc(var(--t) * .5px))movement value को 270px तक limit करता है- duration को सटीक रूप से control करना हो तो
--tको ही limit किया जा सकता है translate: calc(min(3000, var(--t)) * (270px / 3000))- यह calculation 3 seconds में 270px move कराती है
-
mod() से repeat करना
- box दाईं ओर move होने के बाद फिर शुरुआत से शुरू हो, इसके लिए mod() का उपयोग किया जाता है
translate: calc(mod(var(--t)/4, 270) * 1px)से offset को repeat कराया जा सकता है
-
sin() से back-and-forth movement बनाना
- back-and-forth movement को sin() से व्यक्त किया जा सकता है
translate: calc(sin(mod(var(--t)/135, 270)) * 135px)की तरह time value को trigonometric function से जोड़ा जाता है
custom easing function
- CSS math functions और
--tvariable से ऐसी custom easing बनाई जा सकती है जोcubic-bezier()से हासिल करना मुश्किल हो सकता है - पहले
--tको0और1के बीच की value तक limit किया जाता है--t01: calc(min(1000, var(--t)) / 1000)1 second में 0 से 1 तक बदलता है
-
ease-out-cubic
ease-out-cubic1 - pow(1 - t, 3)calculation formula से बनता है--ease-out-cubicvalue बनाने के बाद इसेtranslate: calc(var(--ease-out-cubic) * 270px)से जोड़ा जाता है
-
ease-out-elastic
ease-out-elasticpow(2, -10t) * sin((10t - .75) * 2/3 * PI) + 1calculation formula से बनता है- इसी तरह
--ease-out-elasticvalue बनाकरtranslateसे multiply करके 270px movement पर apply किया जाता है
css-doodle से formulas छोटा करना
- formula जटिल होने पर
var()औरcalc()code को पढ़ना कठिन बना देते हैं - css-doodle के latest version ने
--tको व्यक्त करने वाला @t function जोड़ा है, और argument के अंदर simple math expressions सीधे ले सकता है rotateexpression इस तरह छोटा हो जाता है- पहले:
rotate: calc(mod(var(--t) / 1000, 10) * 5deg) css-doodle:rotate: @t(/1000, %10, *5deg)
- पहले:
- keyframes लिखे बिना भी short code से math-based animations बनाए जा सकते हैं
- parameters बदलकर नए results को जल्दी experiment किया जा सकता है
-
@T और @TS
@tके अलावा uppercase @T दिन की शुरुआत से time ticks को दर्शाता है- @TS
@t(/1000)का shorthand है और time को seconds में track करता है - clock example CodePen पर देखा जा सकता है
- second hand:
rotate: @TS(*6, %360deg) - minute hand:
rotate: @TS(/60, *6, %360deg) - hour hand:
rotate: @TS(/60, /12, *6, %360deg)
-
round() से second hand jump बनाना
- second hand को jump करते हुए move कराना हो तो round() का उपयोग किया जा सकता है
round()का तीसरा parameter rounding interval specify करता है- clock में एक step
360 / 60 = 6degहोता है, इसलिएrotate: round(down, @TS(*6, %360deg), 6deg)का उपयोग किया जाता है
demos और लागू करने के points
- color और position को साथ animate करने वाला example CodePen पर देखा जा सकता है
- text color animation example CodePen पर है
- keyframes ज्यादा intuitive लग सकते हैं, लेकिन जिन demo scenes में math calculations और input variables ज्यादा होते हैं, वहां time को variable के रूप में उपयोग करने का तरीका ज्यादा विविध results बनाना आसान बनाता है
- 17 मई 2024 के update में text color animation demo जोड़ा गया
1 टिप्पणियां
Hacker News की टिप्पणियाँ
अगर आप JS से progress को control करना चाहते हैं, तो negative animation-delay value इस्तेमाल करना भी सुझाऊँगा
उदाहरण के लिए
animation-delay: -1500msanimation को तुरंत शुरू करता है, लेकिन 1.5 सेकंड वाले point पर skip कर देता हैइस value को JS से control करने पर CSS animation को JS से व्यवहार में scrub किया जा सकता है, जिससे सभी animations को game engine-जैसे compute-update-render tick loop के साथ sync किया जा सकता है
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-d...
simple easing function या एक-दो channels के basic keyframes से थोड़ा भी complex होते ही इस approach की limits जल्दी सामने आ जाती हैं
पिछले कुछ सालों से Theatre.js इस्तेमाल कर रहा हूँ और काफी संतुष्ट हूँ
यह library दो हिस्सों में बंटी है: timeline में keyframes और Bezier curves edit करने के लिए studio UI, और उन keyframes को timeline के आधार पर interpolate करने वाला runtime
अगर कई animations को मिलाकर चलाना हो, तो इसे आज़माने लायक है
https://www.theatrejs.com/
बहुत प्रभावशाली है, लेकिन किसी तरह ऐसा भी लगता है कि हम अब जाकर उन चीज़ों के करीब पहुँच रहे हैं जो दशकों पहले Flash से संभव थीं
मैं Flash की वापसी नहीं चाहता, लेकिन CSS animations बनाने के लिए और user-friendly tools हों तो अच्छा होगा
CSS में अब
mod(),round(), trigonometric functions जैसी math functions के लिए पर्याप्त support आ चुका हैCSS JavaScript की तरह timer शुरू नहीं कर सकता, लेकिन आजकल CSS Houdini API से millisecond-level time track करने वाले custom variables define किए जा सकते हैं
लेकिन जब JavaScript है तो यह सब क्यों चाहिए?
क्या drawing layer को drawing primitives पर focus नहीं करना चाहिए? उसमें और higher-level features क्यों डाले जा रहे हैं?
अगर आप animation के लिए JS में trigonometric functions चला रहे हैं, तो शायद हर millisecond UI update करने के लिए DOM भी manipulate कर रहे होंगे, और उसकी cost बहुत ज़्यादा है
Drawing उस DOM से driven होती है जो HTML से बना होता है या JS से update होता है
CSS बस DOM के साथ क्या करना है, इसके parameters painting engine को देता है और defaults को override करते हुए ऊपर से लागू होता है
यह DOM blocks add भी कर सकता है, complex algorithms से positioning behavior बदल भी सकता है, और margin भी असल में इतना simple नहीं है
मैं इसे बेहतरीन समाधान नहीं मानता, लेकिन लगता है इसकी शुरुआत इसलिए हुई कि DOM rendering के दौरान colors बदलने के लिए HTML code update न करना पड़े
शायद इसलिए कि HTML code update करना बिल्कुल मज़ेदार नहीं था, लेकिन मेरे हिसाब से शुरुआत में ही गलत problem solve की गई
उस समय “webmaster” era भी था, यह बात अलग है
पढ़ना आसान होता है अगर fetch logic के अंदर loader DOM element की geometric progress logic—जैसे rotation angle calculate करना और inline style apply करना—मिली-जुली न हो
मुझे पता है कि आजकल chocolate और peanut butter को अलग रखना popular नहीं है, लेकिन ऐसी conventions boundaries बनाती हैं, जिससे यह अंदाज़ा लगाना आसान होता है कि code कहाँ होगा और कहाँ डालना चाहिए
मज़ाक अलग, CSS declarative है और JS व CSS से solve की जा सकने वाली problems का overlap होना स्वाभाविक है
हाल में CSS में जुड़ रहे नए features को लेकर मैं सच में excited हूँ, और interpreted code का कम होना अच्छी बात है
लेख में इस्तेमाल किया गया custom CSS
@propertyशानदार है, और browser support भी 88% है [1]हालांकि fallback
initial-valueset करते समय browser-specific behavior differences से सावधान रहना चाहिएChrome तब
initial-valueइस्तेमाल करता है जब CSS variable define न हो या invalid value पर set होFirefox केवल तब
initial-valueइस्तेमाल करता है जब variable define न होज़्यादातर projects में यह समस्या नहीं होगी, लेकिन हाल के एक project में browser implementation differences को match करने के लिए Firefox में default value JavaScript से set करनी पड़ी
[1] https://caniuse.com/?search=%40property
about:configमें जाकरlayout.css.properties-and-values.enabledको enable कर दें:root{}में defined property value लेना:getComputedStyle(document.documentElement).getPropertyValue("--some-custom-css-var");property value set करना:
document.documentElement.style.setProperty("--some-custom-css-var", "some value");जिन browsers में अभी CSS
@propertysupport enabled नहीं है, वहाँ इसे polyfill की तरह इस्तेमाल किया जा सकता हैlatest Android Chrome में दिलचस्प बात यह है कि Experimental feature flags के बिना भी
mod()से पहले वाले demos चलते हैं, लेकिनmod()औरsin()कुछ भी नहीं करतेकुछ समय से मुझे यह इसलिए चाहिए था क्योंकि मैं box-breathing जैसी चीज़ बनाना चाहता था
मैं inhale-pause-exhale-pause stages को शरीर और desired effect के हिसाब से पूरी तरह adjust कर सकना चाहता था
इस page की approach जैसी किसी चीज़ के बिना, JS के बिना या हास्यास्पद complexity के बिना इसे implement करने का तरीका नहीं मिला
वाह, stylesheets! इस page के demos सच में creative हैं
लेख सच में बहुत अच्छा लिखा गया है
Chrome ने अभी CSS
mod()support को stable release में official रूप से release नहीं किया है, इसलिए अगर आप Chrome preview release नहीं इस्तेमाल कर रहे हैं तो page के ज़्यादातर examples animate नहीं होंगेअगर tick control की ज़रूरत नहीं है और सभी browsers में सिर्फ smooth CSS animations चाहिए, तो FLIP technique उपयोगी है
https://medium.com/outsystems-experts/flip-your-60-fps-anima...
page के bottom पर animation बहुत impressive है
यह individual elements से ज़्यादा एक video जैसी दिखती है
https://RTCode.io बिना refresh और बिना state reset के चलने वाला real-time web playground है, इसलिए CSS animations या transitions पर काम करने वालों के लिए बहुत मददगार हो सकता है
demo https://RTCode.io पर है
Pen import करने के लिए URL के hostname को
xcodepen.ioमें बदल दें