कैरसेल स्लाइड इफ़ेक्ट बनाना

कैरसेल स्लाइड इफ़ेक्ट, कैरसेल को विज़ुअल तौर पर दिलचस्प बनाने का एक शानदार तरीका है. जब उपयोगकर्ता स्लाइड स्क्रोल करता है, तो हर स्लाइड स्क्रोलपोर्ट में आते समय, बीच में होने पर, और बाहर निकलते समय ऐनिमेट हो सकती है. उदाहरण के लिए, स्लाइड फ़ेड इन और फ़ेड आउट हो सकती हैं, घूम सकती हैं या उनका साइज़ बदल सकता है. इससे उपयोगकर्ताओं को डाइनैमिक और दिलचस्प अनुभव मिलता है. एंट्री/एग्ज़िट के लिए इस्तेमाल होने वाले सामान्य ऐनिमेशन के उलट, यह इफ़ेक्ट एक ही लगातार चलने वाले ऐनिमेशन का इस्तेमाल करता है. इससे पूरे स्क्रोलपोर्ट पर स्लाइड के दिखने के तरीके को कंट्रोल किया जा सकता है.

इन्हें कैसे लागू करें

कैरसेल स्लाइड इफ़ेक्ट बनाने का तरीका यहां बताया गया है:

  1. स्क्रोलर बनाएं: यह एलिमेंट, आपके कैरसेल की स्लाइड के लिए कंटेनर के तौर पर काम करेगा. इस उदाहरण में, हॉरिज़ॉन्टल स्क्रोलिंग की अनुमति देने के लिए, overflow-x: scroll का इस्तेमाल किया गया है.

    <ul class="scroller">
      <li class="entry">1</li>
      <li class="entry">2</li>
      <li class="entry">3</li>
      …
    </ul>
    
    .scroller {
      overflow-x: scroll;
    }
    
  2. ऐनिमेशन तय करना: एक सीएसएस ऐनिमेशन बनाएं, जो स्क्रोलपोर्ट से गुज़रने पर आपकी स्लाइड की अलग-अलग स्थितियों को तय करता हो. ऐनिमेशन के किसी भी हिस्से के लिए कीफ़्रेम तय किए जा सकते हैं. उदाहरण के लिए, 50% कीफ़्रेम शामिल करके, यह तय किया जा सकता है कि स्लाइड, स्क्रोलपोर्ट के बीच में कब दिखें. इस उदाहरण में, scale प्रॉपर्टी की वजह से स्लाइड, सेंटर के पास आने पर बड़ी हो जाती हैं और दूर जाने पर छोटी हो जाती हैं.

    @keyframes animate {
      0% {
        scale: 0.5;
      }
      50% {
        scale: 1;
      }
      100% {
        scale: 0.5;
      }
    }
    
  3. ऐनिमेशन और view-timeline लागू करें: ऐनिमेशन को कैरसेल स्लाइड से अटैच करें और उसे किसी view-timeline से लिंक करें. इससे कंटेनर में स्क्रोल करते समय एलिमेंट को ट्रैक किया जा सकेगा.

    .scroller > * {
      animation: animate auto linear both;
      animation-timeline: view(inline);
    }
    

    डिफ़ॉल्ट रूप से, view() एलिमेंट को block ऐक्सिस पर ट्रैक करता है. अगर आपको inline ऐक्सिस पर इसे ट्रैक करना है, तो view(inline) का इस्तेमाल करें.

कोड का उदाहरण

यह कोड, स्क्रोल करने पर हॉरिज़ॉन्टल स्क्रोलर के कैरसेल आइटम को ऐनिमेट करता है. इसके लिए, anonymous view-timeline का इस्तेमाल किया जाता है:

@keyframes animate {
  0% {
    scale: 0.5;
  }

  50% {
    scale: 1;
  }

  100% {
    scale: 0.5;
  }
}

.scroller > * {
  /* Applies the animation using an `auto` duration */
  animation: animate auto linear both;
  /* Sets the animation timeline to use an anonymous view progress timeline, tracking the element's progress through the scroller on the inline axis */
  animation-timeline: view(inline);
}

यह कोड, नाम वाली व्यू-टाइमलाइन का इस्तेमाल करके, स्क्रोल करने पर हॉरिज़ॉन्टल स्क्रोलर के कैरसेल आइटम को ऐनिमेट करता है:

@keyframes animate {
  0% {
    scale: 0.5;
  }

  50% {
    scale: 1;
  }

  100% {
    scale: 0.5;
  }
}

/* This creates a named view-timeline on each carousel item. The timeline is used to drive the animation that is applied on the same element. */
.scroller > * {
  /* Applies the animation using an `auto` duration */
  animation: animate auto linear both;
  /* Defines a named view progress timeline, tracking the element's progress through the scroller on the inline axis */
  view-timeline: --item inline;
  /* Sets the animation timeline to use the named view progress timeline defined above */
  animation-timeline: --item;
}

सबसे सही तरीके

स्क्रोल-ड्रिवन ऐनिमेशन का इस्तेमाल करते समय, कुछ सबसे सही तरीकों को अपनाना ज़रूरी है. इससे यह पक्का किया जा सकता है कि उपयोगकर्ताओं को बेहतर और सुलभ अनुभव मिले:

  • ज़रूर शामिल करें: सभी ब्राउज़र, स्क्रोल-ड्रिवन ऐनिमेशन के साथ काम नहीं करते. @supports ((animation-timeline: view()) and (animation-range: entry)) का इस्तेमाल करके देखें कि यह सुविधा काम करती है या नहीं. साथ ही, उन ब्राउज़र के लिए फ़ॉलबैक उपलब्ध कराएं जिन पर यह सुविधा काम नहीं करती.
    • यहां (animation-range: entry) की जांच ज़रूर शामिल की जानी चाहिए, ताकि उन ब्राउज़र को फ़िल्टर किया जा सके जो सिर्फ़ कुछ हद तक काम करते हैं.
    • फ़ॉलबैक रणनीति के लिए, scroll-timeline-polyfill पैकेज का इस्तेमाल न करें. ऐसा इसलिए, क्योंकि इसमें सभी सुविधाएं मौजूद नहीं हैं और इसमें कई समस्याएं हैं.
    • अगर ऐनिमेशन को सिर्फ़ सजावट के लिए इस्तेमाल किया जा रहा है, तो प्रोग्रेसिव एनहैंसमेंट का विकल्प चुनें और फ़ॉलबैक न दें.
  • उपयोगकर्ता की प्राथमिकताओं का ध्यान रखें: कुछ उपयोगकर्ताओं को वेब पर कम मोशन पसंद होता है. इन उपयोगकर्ताओं के लिए, ऐनिमेशन बंद करने या कम करने के लिए, prefers-reduced-motion मीडिया क्वेरी का इस्तेमाल करें.
  • सिर्फ़ अच्छी परफ़ॉर्मेंस वाली सीएसएस प्रॉपर्टी को ऐनिमेट करने की कोशिश करें: सबसे आसान ऐनिमेशन के लिए, ऐसी प्रॉपर्टी को ऐनिमेट करें जिन्हें ब्राउज़र के कंपोज़िटर थ्रेड से मैनेज किया जा सकता है. जैसे, transform और opacity. width या height जैसी अन्य प्रॉपर्टी को ऐनिमेट करने से, परफ़ॉर्मेंस से जुड़ी समस्याएं हो सकती हैं.
  • DO डिक्लेरेशन के सही क्रम का इस्तेमाल करें: animation शॉर्टहैंड प्रॉपर्टी का इस्तेमाल करते समय, animation-timeline और animation-range को इसके बाद डिक्लेयर करें. इससे शॉर्टहैंड को टाइमलाइन रीसेट करने से रोका जा सकेगा.

जब एक ही टाइमलाइन के आधार पर कई डीओएम एलिमेंट को ऐनिमेट करना हो या उस एलिमेंट के चाइल्ड एलिमेंट को ऐनिमेट करना हो जिस पर view-timeline तय किया गया है, तो नाम वाले view-timeline को प्राथमिकता दें. अगर ऐनिमेट किया जाने वाला एलिमेंट, view-timeline को तय करने वाला एलिमेंट भी है, तो view() का इस्तेमाल करके, बिना नाम वाली व्यू-टाइमलाइन का इस्तेमाल किया जा सकता है.

स्क्रोल-ड्रिवन ऐनिमेशन बनाने के लिए, view() फ़ंक्शन का इस्तेमाल करते समय:

  • ज़रूरी नहीं ट्रैक करने के लिए ऐक्सिस के बारे में साफ़ तौर पर बताएं: डिफ़ॉल्ट block ऐक्सिस को टारगेट न करने पर (जैसे कि हॉरिज़ॉन्टल स्क्रोलर में), साफ़ तौर पर बताएं कि किस ऐक्सिस को view(block) या view(inline) के साथ ट्रैक करना है.

स्क्रोल-ड्रिवन ऐनिमेशन बनाने के लिए, view-timeline प्रॉपर्टी का इस्तेमाल करते समय:

  • नाम के लिए, सीएसएस <dashed-ident> का इस्तेमाल करें (जैसे, view-timeline: --my-custom-name)
  • ज़रूरी नहीं ट्रैक करने के लिए ऐक्सिस के बारे में साफ़ तौर पर बताएं: डिफ़ॉल्ट block ऐक्सिस को टारगेट न करने पर (जैसे, हॉरिज़ॉन्टल स्क्रोलर में), साफ़ तौर पर बताएं कि view-timeline-axis के साथ किस ऐक्सिस को ट्रैक करना है.
  • ज़रूर करें: पक्का करें कि लुकअप का स्कोप काम करता हो. जब view-timeline का एलान करने वाला एलिमेंट, ऐनिमेशन वाले एलिमेंट का फ़्लैट ट्री ऐंसेस्टर न हो, तो शेयर किए गए ऐंसेस्टर पर timeline-scope का इस्तेमाल करके, view-timeline के नाम की विज़िबिलिटी को बढ़ाएं.

ब्राउज़र से जुड़ी सहायता और फ़ॉलबैक रणनीतियां

इसलिए, आम तौर पर फ़ॉलबैक रणनीति की ज़रूरत होती है.

स्क्रोल-ड्रिवन ऐनिमेशन की सुविधा काम न करने वाले ब्राउज़र के लिए, फ़ॉलबैक का इस्तेमाल करके विज़ुअल इफ़ेक्ट फिर से बनाए जा सकते हैं. फ़ॉलबैक आम तौर पर, स्क्रोल लिसनर (ScrollTimeline इफ़ेक्ट के लिए) या IntersectionObserver API (ViewTimeline इफ़ेक्ट के लिए) की मदद से बनाए जाते हैं.

जिन ब्राउज़र में स्क्रोल-ड्रिवन ऐनिमेशन की सुविधा पहले से मौजूद होती है उनमें हमेशा नेटिव सीएसएस का इस्तेमाल करें. ऐसा इसलिए, क्योंकि वे ज़्यादा बेहतर तरीके से काम करते हैं.

ध्यान दें कि फ़ॉलबैक तरीके का इस्तेमाल करके, हर इफ़ेक्ट को फिर से नहीं बनाया जा सकता.

खास तौर पर इस इस्तेमाल के उदाहरण के लिए, यहां दी गई स्क्रिप्ट उन ब्राउज़र के लिए फ़ॉलबैक लागू करती है जो स्क्रोल-ड्रिवन ऐनिमेशन के साथ काम नहीं करते. यह कैरसेल में मौजूद हर आइटम के लिए, रोके गए ऐनिमेशन बनाने के लिए Web Animations API (Element.animate()) का इस्तेमाल करता है. इसके बाद, यह स्क्रोलर पर scroll इवेंट को सुनता है. साथ ही, स्क्रोलर में आइटम की स्क्रोल प्रोग्रेस के आधार पर, हर ऐनिमेशन के currentTime को अपडेट करता है.

// Fallback for browsers that don't support scroll-driven animations
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
  const scroller = document.querySelector('.scroller');
  const entries = document.querySelectorAll('.entry');

  // Create a map to store animations
  const animations = new Map();

  entries.forEach(entry => {
    const animation = entry.animate(
      {
        scale: ['0.5', '1', '0.5']
      },
      {
        duration: 1, // We'll control the time ourselves
        fill: 'both'
      }
    );
    animation.pause();
    animations.set(entry, animation);
  });

  // Update animations on scroll
  const tick = () => {
    const scrollerRect = scroller.getBoundingClientRect();

    entries.forEach(entry => {
      const animation = animations.get(entry);
      if (!animation) return;

      const entryRect = entry.getBoundingClientRect();
      const progress = (entryRect.left + entryRect.width / 2 - scrollerRect.left) / scrollerRect.width;

      animation.currentTime = progress;
    });
  };
    
  scroller.addEventListener('scroll', tick);
  tick();
}