ক্যারোজেল স্লাইড এফেক্ট তৈরি করুন

ক্যারোজেলে ভিজ্যুয়াল আগ্রহ যোগ করার একটি দুর্দান্ত উপায় হল ক্যারোজেল স্লাইড এফেক্ট। ব্যবহারকারী স্লাইডগুলি স্ক্রল করার সাথে সাথে, প্রতিটি স্লাইড স্ক্রলপোর্টে প্রবেশ, কেন্দ্র এবং প্রস্থান করার সময় অ্যানিমেট করতে পারে। যেমন, স্লাইড ফেড ইন ও আউট, রোটেট বা সাইজ স্কেল করা যেতে পারে। এটি একটি ডাইনামিক এবং আকর্ষণীয় ব্যবহারকারীর অভিজ্ঞতা তৈরি করে। সাধারণ এন্ট্রি/এক্সিট অ্যানিমেশনের মতো নয়, এই এফেক্ট সম্পূর্ণ স্ক্রলপোর্ট জুড়ে স্লাইডের উপস্থিতি নিয়ন্ত্রণ করতে একটিই, অবিচ্ছিন্ন অ্যানিমেশন ব্যবহার করে।

কীভাবে প্রয়োগ করতে হয়

ক্যারোজেল স্লাইড এফেক্ট কীভাবে তৈরি করবেন তা এখানে দেওয়া হল:

  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. অ্যানিমেশন নির্ধারণ করুন: একটি CSS অ্যানিমেশন তৈরি করুন যা আপনার স্লাইডগুলি স্ক্রোলপোর্ট অতিক্রম করার সময় তাদের বিভিন্ন অবস্থা নির্ধারণ করে। আপনি অ্যানিমেশনের যেকোনও অংশের জন্য কীফ্রেম নির্ধারণ করতে পারবেন। যেমন, আপনি 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) ব্যবহার করতে পারেন।

কোডের উদাহরণ

এই কোডটি অ্যানোনিমাস ভিউ-টাইমলাইন ব্যবহার করে স্ক্রল করার সময় হরাইজন্টাল স্ক্রলারের ক্যারোজেল আইটেম অ্যানিমেট করে:

@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 মিডিয়া কোয়েরি ব্যবহার করুন।
  • শুধুমাত্র পারফর্ম্যান্ট CSS প্রপার্টি অ্যানিমেট করার চেষ্টা করুন: সবচেয়ে মসৃণ অ্যানিমেশনের জন্য, ব্রাউজারের কম্পোজিটর থ্রেড দ্বারা ম্যানেজ করা যায় এমন প্রপার্টি অ্যানিমেট করুন, যেমন transform এবং opacity। width বা height-এর মতো অন্যান্য প্রপার্টি অ্যানিমেট করলে পারফর্ম্যান্স সংক্রান্ত সমস্যা হতে পারে।
  • সঠিক ডিক্লারেশন অর্ডার ব্যবহার করুন: animation শর্টহ্যান্ড প্রপার্টি ব্যবহার করার সময়, শর্টহ্যান্ড যাতে টাইমলাইন রিসেট না করে দেয় তার জন্য animation-timeline এবং animation-range এর পরে ডিক্লেয়ার করুন।

একাধিক DOM এলিমেন্টকে একই টাইমলাইনের ভিত্তিতে অ্যানিমেট করতে হলে অথবা যে এলিমেন্টের উপর view-timeline সংজ্ঞায়িত করা আছে তার চিলড্রেনকে অ্যানিমেট করতে হলে, নামযুক্ত view-timeline ব্যবহার করা ভালো। আপনি যে এলিমেন্ট অ্যানিমেট করছেন সেটি যদি view-timeline-কে সংজ্ঞায়িত করে, তাহলে আপনি view() ব্যবহার করে একটি অ্যানোনিমাস ভিউ-টাইমলাইন ব্যবহার করতে পারবেন।

স্ক্রল-চালিত অ্যানিমেশন তৈরি করতে view() ফাংশন ব্যবহার করার সময়:

  • ঐচ্ছিক ট্র্যাক করার জন্য অক্ষ সম্পর্কে স্পষ্ট হোন: ডিফল্ট block অক্ষকে টার্গেট না করার সময় (যেমন অনুভূমিক স্ক্রোলারে), view(block) বা view(inline)-এর মাধ্যমে কোন অক্ষ ট্র্যাক করতে হবে সে সম্পর্কে স্পষ্ট হোন।

স্ক্রল-চালিত অ্যানিমেশন তৈরি করতে view-timeline প্রপার্টি ব্যবহার করার সময়:

  • নামের জন্য CSS <dashed-ident> ব্যবহার করুন (যেমন, view-timeline: --my-custom-name)
  • ঐচ্ছিক ট্র্যাক করার জন্য অক্ষ সম্পর্কে স্পষ্ট হোন: ডিফল্ট block অক্ষকে টার্গেট না করার সময় (যেমন একটি অনুভূমিক স্ক্রোলারে), view-timeline-axis-এর সাথে কোন অক্ষ ট্র্যাক করতে হবে সে সম্পর্কে স্পষ্ট হোন।
  • view-timeline ঘোষণা করা এলিমেন্টটি অ্যানিমেট করা এলিমেন্টের ফ্ল্যাট ট্রি পূর্বপুরুষ না হলে, শেয়ার করা পূর্বপুরুষের উপর timeline-scope ব্যবহার করে view-timeline-এর নামের দৃশ্যমানতা বাড়ান: লুকআপের স্কোপ কাজ করছে কিনা তা নিশ্চিত করুন।

ব্রাউজার সাপোর্ট ও ফলব্যাক স্ট্র্যাটেজি

তাই, সাধারণত একটি ফলব্যাক স্ট্র্যাটেজি প্রয়োজন হয়।

যেসব ব্রাউজারে স্ক্রল-চালিত অ্যানিমেশন কাজ করে না, সেখানে ভিজ্যুয়াল এফেক্ট আবার তৈরি করতে আপনি ফলব্যাক ব্যবহার করতে পারেন। ফলব্যাক সাধারণত স্ক্রল লিসেনার (ScrollTimeline এফেক্টের জন্য) বা IntersectionObserver API (ViewTimeline এফেক্টের জন্য) দিয়ে তৈরি করা হয়।

স্ক্রল-চালিত অ্যানিমেশনের জন্য বিল্ট-ইন সাপোর্ট সহ ব্রাউজারে, সর্বদা নেটিভ CSS ইমপ্লিমেন্টেশন ব্যবহার করুন কারণ সেগুলি আরও বেশি পারফর্ম্যান্স দেয়।

মনে রাখবেন, ফলব্যাক অ্যাপ্রোচ ব্যবহার করে সব এফেক্ট আবার তৈরি করা যায় না।

বিশেষ করে এই ব্যবহারের ক্ষেত্রে, স্ক্রল-চালিত অ্যানিমেশন কাজ করে না এমন ব্রাউজারের জন্য নিম্নলিখিত স্ক্রিপ্ট ফলব্যাক প্রয়োগ করে। ক্যারোজেলের প্রতিটি আইটেমের জন্য পজ করা অ্যানিমেশন তৈরি করতে এটি 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();
}