7 पॉइंट द्वारा GN⁺ 2024-05-06 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • 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 --t define करके millisecond-level time track किया जा सकता है
  • basic example में @property --t को <integer> के रूप में declare किया जाता है, @keyframes tick में इसे 0 से 86400000 तक बदलाया जाता है, और :root पर 86400000ms linear infinite animation apply की जाती है
  • --t हर 1 millisecond में 1 से बढ़ता है और 1 second में 1000 हो जाता है
  • counter() का उपयोग करके current --t value को 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)))

बढ़ती time value को animation value में बदलना

  • --t value लगातार एक ही दिशा में बढ़ती रहती है
  • angle value 360deg से आगे जाए तो भी ठीक है, लेकिन सभी 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 और --t variable से ऐसी 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-cubic 1 - pow(1 - t, 3) calculation formula से बनता है
    • --ease-out-cubic value बनाने के बाद इसे translate: calc(var(--ease-out-cubic) * 270px) से जोड़ा जाता है
  • ease-out-elastic

    • ease-out-elastic pow(2, -10t) * sin((10t - .75) * 2/3 * PI) + 1 calculation formula से बनता है
    • इसी तरह --ease-out-elastic value बनाकर translate से multiply करके 270px movement पर apply किया जाता है

css-doodle से formulas छोटा करना

  • formula जटिल होने पर var() और calc() code को पढ़ना कठिन बना देते हैं
  • css-doodle के latest version ने --t को व्यक्त करने वाला @t function जोड़ा है, और argument के अंदर simple math expressions सीधे ले सकता है
  • rotate expression इस तरह छोटा हो जाता है
    • पहले: 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 टिप्पणियां

 
GN⁺ 2024-05-06
Hacker News की टिप्पणियाँ
  • अगर आप JS से progress को control करना चाहते हैं, तो negative animation-delay value इस्तेमाल करना भी सुझाऊँगा
    उदाहरण के लिए animation-delay: -1500ms animation को तुरंत शुरू करता है, लेकिन 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...

    • तो क्या इससे iOS-style scroll offset-based animation भी संभव नहीं हो जाएगी?
  • 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 क्यों डाले जा रहे हैं?

    • यह नहीं भूलना चाहिए कि CSS animations hardware-accelerated होती हैं
      अगर आप animation के लिए JS में trigonometric functions चला रहे हैं, तो शायद हर millisecond UI update करने के लिए DOM भी manipulate कर रहे होंगे, और उसकी cost बहुत ज़्यादा है
    • CSS drawing layer नहीं है
      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 भी था, यह बात अलग है
    • एक फायदा जो दिमाग में आता है, वह है application logic और presentation का separation
      पढ़ना आसान होता है अगर fetch logic के अंदर loader DOM element की geometric progress logic—जैसे rotation angle calculate करना और inline style apply करना—मिली-जुली न हो
      मुझे पता है कि आजकल chocolate और peanut butter को अलग रखना popular नहीं है, लेकिन ऐसी conventions boundaries बनाती हैं, जिससे यह अंदाज़ा लगाना आसान होता है कि code कहाँ होगा और कहाँ डालना चाहिए
    • JS मूल रूप से single-threaded है; हाँ, workers ज़रूर हैं, लेकिन UI को stable frame rate पर बनाए रखने के लिए जो भी काम कहीं और offload किया जा सके, वह अच्छा है
    • CSS में WebSocket आने तक इंतज़ार करते हैं!
      मज़ाक अलग, CSS declarative है और JS व CSS से solve की जा सकने वाली problems का overlap होना स्वाभाविक है
      हाल में CSS में जुड़ रहे नए features को लेकर मैं सच में excited हूँ, और interpreted code का कम होना अच्छी बात है
  • लेख में इस्तेमाल किया गया custom CSS @property शानदार है, और browser support भी 88% है [1]
    हालांकि fallback initial-value set करते समय 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

    • अगर Firefox में demo try करना चाहते हैं, तो about:config में जाकर layout.css.properties-and-values.enabled को enable कर दें
    • ज़रूरत पड़ने पर JavaScript से property value set करने का तरीका यह है
      :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 @property support 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 हैं

    • वह तो बस CSS की animation curve नहीं है?
  • लेख सच में बहुत अच्छा लिखा गया है
    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 में बदल दें

    • क्या किसी ने RTCode इस्तेमाल किया है? दिलचस्प लगता है, लेकिन homepage देखकर थोड़ा confusing है कि यह real-time support वाला CodePen alternative है, या production में भी इस्तेमाल किया जा सकता है