স্ক্রোল-চালিত অ্যানিমেশনগুলির সাথে স্ক্রলে উপাদানগুলিকে অ্যানিমেট করুন

ডিক্লারেটিভ পদ্ধতিতে স্ক্রল-চালিত অ্যানিমেশন তৈরি করতে স্ক্রল টাইমলাইন এবং ভিউ টাইমলাইন কীভাবে ব্যবহার করতে হয় তা শিখুন।

প্রকাশিত: ৫ মে, ২০২৩

স্ক্রোল-চালিত অ্যানিমেশন

Browser Support

  • ক্রোম: ১১৫।
  • প্রান্ত: ১১৫।
  • ফায়ারফক্স টেকনোলজি প্রিভিউ: সমর্থিত।
  • সাফারি: ২৬।

Source

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

ডকুমেন্টের শীর্ষে থাকা একটি পঠন নির্দেশক, যা স্ক্রল দ্বারা চালিত হয়।

একই ধরনের স্ক্রল-চালিত অ্যানিমেশন হলো এমন একটি অ্যানিমেশন যা কোনো এলিমেন্টের স্ক্রল কন্টেইনারের ভেতরের অবস্থানের সাথে সংযুক্ত থাকে। এর মাধ্যমে, উদাহরণস্বরূপ, এলিমেন্টগুলো দৃশ্যমান হওয়ার সাথে সাথে ধীরে ধীরে দৃশ্যমান হতে পারে।

এই পৃষ্ঠার ছবিগুলো ধীরে ধীরে দৃশ্যমান হয়।

এই ধরনের প্রভাব অর্জনের প্রচলিত উপায় হলো প্রধান থ্রেডে স্ক্রল ইভেন্টে সাড়া দেওয়া, যার ফলে দুটি প্রধান সমস্যা দেখা দেয়:

  • আধুনিক ব্রাউজারগুলো একটি পৃথক প্রসেসে স্ক্রলিংয়ের কাজ করে এবং একারণে স্ক্রল ইভেন্টগুলো অ্যাসিঙ্ক্রোনাসভাবে সরবরাহ করে।
  • প্রধান থ্রেডের অ্যানিমেশনগুলোতে জ্যাঙ্ক দেখা দিতে পারে

এর ফলে স্ক্রলিংয়ের সাথে সামঞ্জস্যপূর্ণ ও উচ্চ কার্যক্ষমতাসম্পন্ন স্ক্রল-চালিত অ্যানিমেশন তৈরি করা অসম্ভব বা অত্যন্ত কঠিন হয়ে পড়ে।

ক্রোম সংস্করণ ১১৫ থেকে এক নতুন সেট এপিআই এবং ধারণা এসেছে যা ব্যবহার করে ডিক্লারেটিভ স্ক্রল-চালিত অ্যানিমেশন চালু করা যায়: স্ক্রল টাইমলাইন এবং ভিউ টাইমলাইন।

এই নতুন ধারণাগুলো বিদ্যমান ওয়েব অ্যানিমেশন এপিআই (WAAPI) এবং সিএসএস অ্যানিমেশন এপিআই-এর সাথে সমন্বিত হয়, যার ফলে এগুলো বিদ্যমান এপিআইগুলোর সুবিধাগুলোও লাভ করতে পারে। এর মধ্যে অন্যতম হলো স্ক্রল-চালিত অ্যানিমেশনগুলোকে মূল থ্রেড থেকে চালানোর ক্ষমতা। হ্যাঁ, আপনি ঠিকই পড়েছেন: এখন আপনি মাত্র কয়েকটি অতিরিক্ত কোডের লাইনের মাধ্যমেই স্ক্রল দ্বারা চালিত অত্যন্ত মসৃণ অ্যানিমেশন মূল থ্রেড থেকে চালাতে পারবেন। এতে অপছন্দ করার কী আছে?!

ওয়েবের অ্যানিমেশন, একটি সংক্ষিপ্ত পর্যালোচনা

CSS দিয়ে ওয়েবে অ্যানিমেশন

CSS-এ অ্যানিমেশন তৈরি করতে, @keyframes অ্যাট-রুল ব্যবহার করে এক সেট কীফ্রেম নির্ধারণ করুন। animation-name প্রপার্টি ব্যবহার করে এটিকে কোনো এলিমেন্টের সাথে লিঙ্ক করুন এবং অ্যানিমেশনটি কতক্ষণ চলবে তা নির্ধারণ করতে একটি animation-duration সেট করুন। আরও অনেক animation-* লংহ্যান্ড প্রপার্টি রয়েছে—যেমন animation-easing-function এবং animation-fill-mode যেগুলোকে animation শর্টহ্যান্ডে একত্রিত করা যায়।

উদাহরণস্বরূপ, এখানে একটি অ্যানিমেশন রয়েছে যা একটি এলিমেন্টকে X-অক্ষ বরাবর বড় করার পাশাপাশি তার ব্যাকগ্রাউন্ডের রঙও পরিবর্তন করে:

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}

জাভাস্ক্রিপ্ট ব্যবহার করে ওয়েবে অ্যানিমেশন

জাভাস্ক্রিপ্টে, ওয়েব অ্যানিমেশন এপিআই ব্যবহার করে ঠিক একই কাজ করা যায়। আপনি নতুন Animation এবং KeyFrameEffect ইনস্ট্যান্স তৈরি করে, অথবা অনেক সংক্ষিপ্ত Element animate() মেথড ব্যবহার করে এটি করতে পারেন।

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

উপরের জাভাস্ক্রিপ্ট কোড স্নিপেটটির এই দৃশ্যমান ফলাফলটি পূর্ববর্তী CSS সংস্করণের অনুরূপ।

অ্যানিমেশন টাইমলাইন

ডিফল্টরূপে, কোনো এলিমেন্টের সাথে সংযুক্ত অ্যানিমেশন ডকুমেন্ট টাইমলাইনে চলে। পেজ লোড হওয়ার সময় এর অরিজিন টাইম ০ থেকে শুরু হয় এবং ঘড়ির সময় বাড়ার সাথে সাথে এটিও সামনের দিকে এগোতে থাকে। এটিই হলো ডিফল্ট অ্যানিমেশন টাইমলাইন এবং এখন পর্যন্ত, এটিই ছিল একমাত্র অ্যানিমেশন টাইমলাইন যা আপনি ব্যবহার করতে পারতেন।

স্ক্রল-চালিত অ্যানিমেশন স্পেসিফিকেশন দুই ধরনের নতুন টাইমলাইন সংজ্ঞায়িত করে যা আপনি ব্যবহার করতে পারেন:

  • স্ক্রল অগ্রগতি টাইমলাইন : একটি টাইমলাইন যা একটি নির্দিষ্ট অক্ষ বরাবর স্ক্রল কন্টেইনারের স্ক্রল অবস্থানের সাথে সংযুক্ত থাকে।
  • অগ্রগতি টাইমলাইন দেখুন : একটি টাইমলাইন যা তার স্ক্রল কন্টেইনারের মধ্যে কোনো নির্দিষ্ট উপাদানের আপেক্ষিক অবস্থানের সাথে সংযুক্ত থাকে।

স্ক্রোল অগ্রগতি টাইমলাইন

স্ক্রল প্রোগ্রেস টাইমলাইন হলো একটি অ্যানিমেশন টাইমলাইন যা একটি নির্দিষ্ট অক্ষ বরাবর স্ক্রল কন্টেইনারের (যাকে স্ক্রলপোর্ট বা স্ক্রলারও বলা হয়) স্ক্রল পজিশনের অগ্রগতির সাথে সংযুক্ত থাকে। এটি একটি স্ক্রল রেঞ্জের মধ্যে থাকা অবস্থানকে অগ্রগতির শতাংশে রূপান্তরিত করে।

স্ক্রল করার শুরুর অবস্থানটি ০% অগ্রগতি এবং শেষের অবস্থানটি ১০০% অগ্রগতি নির্দেশ করে। নিচের চিত্রটিতে আপনি দেখতে পাচ্ছেন যে, স্ক্রলারটি উপর থেকে নিচে স্ক্রল করার সাথে সাথে অগ্রগতি ০% থেকে ১০০% পর্যন্ত বাড়তে থাকে।

স্ক্রল অগ্রগতির টাইমলাইনের দৃশ্যায়ন। আপনি স্ক্রলারের একেবারে নিচে স্ক্রল করার সাথে সাথে, অগ্রগতির মান ০% থেকে ১০০% পর্যন্ত বাড়তে থাকে।

✨ নিজেই চেষ্টা করে দেখুন

স্ক্রল প্রোগ্রেস টাইমলাইনকে প্রায়শই সংক্ষেপে শুধু “স্ক্রল টাইমলাইন” বলা হয়।

অগ্রগতির সময়রেখা দেখুন

এই ধরনের টাইমলাইন একটি স্ক্রল কন্টেইনারের ভেতরের কোনো নির্দিষ্ট উপাদানের আপেক্ষিক অগ্রগতির সাথে যুক্ত থাকে। স্ক্রল প্রোগ্রেস টাইমলাইনের মতোই, একটি স্ক্রলারের স্ক্রল অফসেট ট্র্যাক করা হয়। তবে স্ক্রল প্রোগ্রেস টাইমলাইনের থেকে ভিন্নভাবে, এক্ষেত্রে সেই স্ক্রলারের ভেতরের কোনো বিষয়ের আপেক্ষিক অবস্থানই তার অগ্রগতি নির্ধারণ করে।

এটি অনেকটা IntersectionObserver কাজের পদ্ধতির সাথে তুলনীয়, যা স্ক্রলারে কোনো এলিমেন্ট কতটা দৃশ্যমান তা ট্র্যাক করতে পারে। যদি এলিমেন্টটি স্ক্রলারে দৃশ্যমান না হয়, তবে এটি ইন্টারসেক্ট করছে না। আর যদি এটি স্ক্রলারের ভেতরে দৃশ্যমান হয়—এমনকি ক্ষুদ্রতম অংশের জন্যও—তবে এটি ইন্টারসেক্ট করছে।

একটি ভিউ প্রোগ্রেস টাইমলাইন সেই মুহূর্ত থেকে শুরু হয় যখন কোনো সাবজেক্ট স্ক্রলারের সাথে ছেদ করতে শুরু করে এবং যখন সাবজেক্টটি স্ক্রলারের সাথে ছেদ করা বন্ধ করে তখন তা শেষ হয়। নিম্নলিখিত ভিজ্যুয়ালাইজেশনে, আপনি দেখতে পারেন যে সাবজেক্টটি স্ক্রল কন্টেইনারে প্রবেশ করার সময় থেকে প্রোগ্রেস গণনা ০% থেকে শুরু হয় এবং সাবজেক্টটি স্ক্রল কন্টেইনার ছেড়ে যাওয়ার ঠিক সেই মুহূর্তে ১০০%-এ পৌঁছায়।

একটি ভিউ প্রোগ্রেস টাইমলাইনের ভিজ্যুয়ালাইজেশন। সাবজেক্টটি (সবুজ বক্স) স্ক্রলার অতিক্রম করার সাথে সাথে প্রোগ্রেস ০% থেকে ১০০% পর্যন্ত গণনা করে।

✨ নিজেই চেষ্টা করে দেখুন

একটি ভিউ প্রোগ্রেস টাইমলাইনকে প্রায়শই সংক্ষেপে শুধু “ভিউ টাইমলাইন” বলা হয়। বিষয়বস্তুর আকারের উপর ভিত্তি করে একটি ভিউ টাইমলাইনের নির্দিষ্ট অংশকে লক্ষ্য করা সম্ভব, তবে সে বিষয়ে পরে আরও আলোচনা করা হবে।

স্ক্রোল অগ্রগতি টাইমলাইনগুলির সাথে ব্যবহারিক হওয়া

CSS-এ একটি বেনামী স্ক্রোল অগ্রগতি টাইমলাইন তৈরি করা

CSS-এ স্ক্রল টাইমলাইন তৈরি করার সবচেয়ে সহজ উপায় হলো scroll() ফাংশনটি ব্যবহার করা। এটি একটি অ্যানোনিমাস স্ক্রল টাইমলাইন তৈরি করে, যা আপনি নতুন animation-timeline প্রপার্টির ভ্যালু হিসেবে সেট করতে পারেন।

উদাহরণ:

@keyframes animate-it {  }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

` scroll() ` ফাংশনটি একটি <scroller> এবং একটি <axis> আর্গুমেন্ট গ্রহণ করে।

<scroller> আর্গুমেন্টের জন্য গ্রহণযোগ্য মানগুলো হলো নিম্নরূপ:

  • nearest : নিকটতম পূর্ববর্তী স্ক্রোল কন্টেইনার ব্যবহার করে (ডিফল্ট)
  • root : ডকুমেন্ট ভিউপোর্টকে স্ক্রল কন্টেইনার হিসেবে ব্যবহার করে।
  • self : এলিমেন্টটিকেই স্ক্রল কন্টেইনার হিসেবে ব্যবহার করে।

<axis> আর্গুমেন্টের জন্য গ্রহণযোগ্য মানগুলো হলো নিম্নরূপ:

  • block : স্ক্রল কন্টেইনারের ব্লক অক্ষ বরাবর অগ্রগতির পরিমাপ ব্যবহার করে (ডিফল্ট)
  • inline : স্ক্রল কন্টেইনারের ইনলাইন অক্ষ বরাবর অগ্রগতির পরিমাপ ব্যবহার করে।
  • y : স্ক্রল কন্টেইনারের y অক্ষ বরাবর অগ্রগতির পরিমাপ ব্যবহার করে।
  • x : স্ক্রল কন্টেইনারের x অক্ষ বরাবর অগ্রগতির পরিমাপ ব্যবহার করে।

উদাহরণস্বরূপ, ব্লক অ্যাক্সিসে রুট স্ক্রলারের সাথে একটি অ্যানিমেশন যুক্ত করতে, scroll() ফাংশনে root এবং block এই মানগুলো পাস করতে হবে। এগুলোকে একসাথে করলে মানটি হয় scroll(root block)

ডেমো: পড়ার অগ্রগতি সূচক

এই ডেমোতে ভিউপোর্টের শীর্ষে একটি রিডিং প্রোগ্রেস ইন্ডিকেটর স্থিরভাবে বসানো আছে। আপনি যখন পৃষ্ঠাটি স্ক্রল করে নিচে নামবেন, প্রোগ্রেস বারটি বড় হতে থাকবে এবং ডকুমেন্টের শেষে পৌঁছে সম্পূর্ণ ভিউপোর্টের প্রস্থ জুড়ে বিস্তৃত হবে। এই অ্যানিমেশনটি পরিচালনা করার জন্য একটি অ্যানোনিমাস স্ক্রল প্রোগ্রেস টাইমলাইন ব্যবহার করা হয়েছে।

ডেমো: পঠন অগ্রগতি সূচক

✨ নিজেই চেষ্টা করে দেখুন

পড়ার অগ্রগতি সূচকটি `position fixed` ব্যবহার করে পৃষ্ঠার শীর্ষে স্থাপন করা হয়েছে। কম্পোজিটেড অ্যানিমেশন ব্যবহার করার জন্য, শুধু width অ্যানিমেট করা হচ্ছে না, বরং একটি ` transform ব্যবহার করে এলিমেন্টটিকে x-অক্ষ বরাবর ছোট করা হচ্ছে।

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

#progress এলিমেন্টের grow-progress অ্যানিমেশনের টাইমলাইনটি scroll() ব্যবহার করে তৈরি একটি অ্যানোনিমাস টাইমলাইনে সেট করা হয়েছে। scroll() এ কোনো আর্গুমেন্ট দেওয়া হয় না, তাই এটি তার ডিফল্ট মানগুলিতে ফিরে যাবে।

ডিফল্টভাবে ট্র্যাক করার জন্য nearest স্ক্রলারটি বেছে নেওয়া হয় এবং ডিফল্ট অ্যাক্সিস হলো block । এর ফলে, #progress এলিমেন্টের সবচেয়ে কাছের স্ক্রলার হিসেবে রুট স্ক্রলারটি কার্যকরভাবে টার্গেট হয় এবং একই সাথে এটি তার ব্লক ডিরেকশন ট্র্যাক করে।

CSS-এ একটি নামযুক্ত স্ক্রোল অগ্রগতি টাইমলাইন তৈরি করা

স্ক্রল প্রোগ্রেস টাইমলাইন সংজ্ঞায়িত করার একটি বিকল্প উপায় হলো একটি নামযুক্ত টাইমলাইন ব্যবহার করা। এটি কিছুটা বেশি বিশদ, কিন্তু যখন আপনি কোনো প্যারেন্ট স্ক্রলার বা রুট স্ক্রলারকে টার্গেট করছেন না, অথবা যখন পেজটিতে একাধিক টাইমলাইন ব্যবহৃত হয়, বা যখন স্বয়ংক্রিয় লুকআপ কাজ করে না, তখন এটি বেশ কাজে আসতে পারে। এই পদ্ধতিতে, আপনি আপনার দেওয়া নামটি দিয়ে একটি স্ক্রল প্রোগ্রেস টাইমলাইনকে শনাক্ত করতে পারেন।

কোনো এলিমেন্টে একটি নামযুক্ত স্ক্রল প্রোগ্রেস টাইমলাইন তৈরি করতে, স্ক্রল কন্টেইনারের scroll-timeline-name CSS প্রপার্টিতে আপনার পছন্দের একটি আইডেন্টিফায়ার সেট করুন। ভ্যালুটি অবশ্যই -- দিয়ে শুরু হতে হবে।

কোন অক্ষটি ট্র্যাক করা হবে তা সূক্ষ্মভাবে পরিবর্তন করতে, scroll-timeline-axis প্রপার্টিটিও ঘোষণা করুন। অনুমোদিত মানগুলি scroll() ফাংশনের <axis> আর্গুমেন্টের মতোই।

অবশেষে, অ্যানিমেশনটিকে স্ক্রল প্রোগ্রেস টাইমলাইনের সাথে লিঙ্ক করতে, যে এলিমেন্টটিকে অ্যানিমেট করতে হবে তার animation-timeline প্রপার্টিতে scroll-timeline-name জন্য ব্যবহৃত আইডেন্টিফায়ারের সমান ভ্যালু সেট করুন।

কোডের উদাহরণ:

@keyframes animate-it {  }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

চাইলে, scroll-timeline-name এবং স্ক্রল scroll-timeline scroll-timeline-axis একত্রিত করতে পারেন। উদাহরণস্বরূপ:

scroll-timeline: --my-scroller inline;

এই ডেমোতে প্রতিটি ইমেজ ক্যারোসেলের উপরে একটি স্টেপ ইন্ডিকেটর দেখানো হয়েছে। যখন একটি ক্যারোসেলে তিনটি ছবি থাকে, তখন ইন্ডিকেটর বারটি ৩৩% প্রস্থ থেকে শুরু হয়, যা নির্দেশ করে যে আপনি বর্তমানে তিনটির মধ্যে প্রথম ছবিটি দেখছেন। যখন শেষ ছবিটি দেখা যায়—যা স্ক্রলারটি শেষ পর্যন্ত স্ক্রল করার মাধ্যমে নির্ধারিত হয়—তখন ইন্ডিকেটরটি স্ক্রলারের সম্পূর্ণ প্রস্থ জুড়ে থাকে। অ্যানিমেশনটি পরিচালনা করার জন্য একটি নামযুক্ত স্ক্রল প্রোগ্রেস টাইমলাইন ব্যবহার করা হয়।

ডেমো: হরাইজন্টাল ক্যারোসেলের ধাপ নির্দেশক

✨ নিজেই চেষ্টা করে দেখুন

একটি গ্যালারির মূল মার্কআপটি হলো এটি:

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

.gallery র‍্যাপার এলিমেন্টের মধ্যে .gallery__progress এলিমেন্টটি অ্যাবসোলিউটলি পজিশনড থাকে। এর প্রাথমিক আকার --num-images কাস্টম প্রপার্টি দ্বারা নির্ধারিত হয়।

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

.gallery__scrollcontainer এলিমেন্টটি এর ভেতরের .gallery__entry এলিমেন্টগুলোকে আনুভূমিকভাবে সাজিয়ে রাখে এবং এটিই সেই এলিমেন্ট যা স্ক্রল করে। এর স্ক্রল পজিশন ট্র্যাক করার মাধ্যমে .gallery__progress অ্যানিমেটেড হয়। এটি করা হয় `Scroll Progress Timeline --gallery__scrollcontainer নামক ফাংশনটিকে রেফার করার মাধ্যমে।

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

জাভাস্ক্রিপ্ট ব্যবহার করে একটি স্ক্রোল অগ্রগতি টাইমলাইন তৈরি করা

জাভাস্ক্রিপ্টে একটি স্ক্রল টাইমলাইন তৈরি করতে, ScrollTimeline ক্লাসের একটি নতুন ইনস্ট্যান্স তৈরি করুন। একটি প্রপার্টি ব্যাগে আপনি যে source এবং axis ট্র্যাক করতে চান তা পাস করুন।

  • source : যে এলিমেন্টের স্ক্রলার আপনি ট্র্যাক করতে চান, তার একটি রেফারেন্স। রুট স্ক্রলারকে টার্গেট করতে document.documentElement ব্যবহার করুন।
  • axis : কোন অক্ষ বরাবর ট্র্যাক করতে হবে তা নির্ধারণ করে। CSS সংস্করণের মতোই, এর গৃহীত মানগুলো হলো block , inline , x , এবং y
const tl = new ScrollTimeline({
  source: document.documentElement,
});

এটিকে কোনো ওয়েব অ্যানিমেশনের সাথে যুক্ত করতে, timeline প্রপার্টি হিসেবে পাস করুন এবং যদি কোনো duration থাকে তবে তা বাদ দিন।

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

ডেমো: পঠন অগ্রগতি সূচক, পুনঃপর্যালোচনা

একই মার্কআপ ব্যবহার করে জাভাস্ক্রিপ্টের সাহায্যে রিডিং প্রোগ্রেস ইন্ডিকেটরটি পুনরায় তৈরি করতে, নিম্নলিখিত জাভাস্ক্রিপ্ট কোডটি ব্যবহার করুন:

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

CSS সংস্করণেও দৃশ্যমান ফলাফল একই: তৈরি করা timeline রুট স্ক্রলারকে অনুসরণ করে এবং আপনি পৃষ্ঠাটি স্ক্রল করার সাথে সাথে x-অক্ষ বরাবর #progress কে ০% থেকে ১০০% পর্যন্ত স্কেল করে।

✨ নিজেই চেষ্টা করে দেখুন

View Progress Timeline-এর সাথে ব্যবহারিক অভিজ্ঞতা

CSS-এ একটি অ্যানোনিমাস ভিউ প্রোগ্রেস টাইমলাইন তৈরি করা

একটি ভিউ প্রোগ্রেস টাইমলাইন তৈরি করতে, view() ফাংশনটি ব্যবহার করুন। এর গৃহীত আর্গুমেন্টগুলো হলো <axis> এবং <view-timeline-inset>

  • <axis> হলো স্ক্রল প্রোগ্রেস টাইমলাইনের মতোই এবং এটি নির্ধারণ করে কোন অক্ষকে ট্র্যাক করতে হবে। এর ডিফল্ট মান হলো block
  • <view-timeline-inset> ব্যবহার করে, কোনো এলিমেন্ট দৃশ্যমান হবে কি না, তা নির্ধারণ করতে আপনি একটি অফসেট (ধনাত্মক বা ঋণাত্মক) নির্দিষ্ট করতে পারেন। এর মান অবশ্যই পার্সেন্টেজ বা auto হতে হবে, যেখানে auto হলো ডিফল্ট মান।

উদাহরণস্বরূপ, ব্লক অ্যাক্সিসে কোনো এলিমেন্টের স্ক্রলারের সাথে ছেদ করার সময় সেটিতে একটি অ্যানিমেশন যুক্ত করতে, view(block) ব্যবহার করুন। scroll() এর মতোই, animation-timeline প্রপার্টির ভ্যালু হিসেবে এটি সেট করুন এবং animation-duration কে auto সেট করতে ভুলবেন না।

নিম্নলিখিত কোডটি ব্যবহার করলে, আপনি স্ক্রোল করার সময় প্রতিটি img ভিউপোর্ট অতিক্রম করার সাথে সাথে ধীরে ধীরে দৃশ্যমান হবে।

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

ইন্টারমেজো: টাইমলাইন পরিসীমা দেখুন

ডিফল্টরূপে, ভিউ টাইমলাইনের সাথে লিঙ্ক করা একটি অ্যানিমেশন সম্পূর্ণ টাইমলাইন পরিসরে সংযুক্ত হয়। এটি সেই মুহূর্ত থেকে শুরু হয় যখন সাবজেক্টটি স্ক্রলপোর্টে প্রবেশ করতে যাচ্ছে এবং সাবজেক্টটি স্ক্রলপোর্ট থেকে সম্পূর্ণরূপে বেরিয়ে গেলে শেষ হয়।

যে পরিসরে এটি সংযুক্ত হবে তা নির্দিষ্ট করে দিয়ে এটিকে ভিউ টাইমলাইনের একটি নির্দিষ্ট অংশের সাথেও লিঙ্ক করা সম্ভব। উদাহরণস্বরূপ, এটি শুধুমাত্র তখনই হতে পারে যখন সাবজেক্টটি স্ক্রলারে প্রবেশ করছে। নিম্নলিখিত ভিজ্যুয়ালাইজেশনে, সাবজেক্টটি স্ক্রল কন্টেইনারে প্রবেশ করার সময় থেকে অগ্রগতি ০% থেকে গণনা শুরু করে, কিন্তু এটি সম্পূর্ণরূপে ছেদ করার মুহূর্ত থেকেই ১০০%-এ পৌঁছে যায়।

সাবজেক্টের প্রবেশের পরিসীমা ট্র্যাক করার জন্য একটি ভিউ টাইমলাইন সেট করা হয়েছে। অ্যানিমেশনটি শুধুমাত্র তখনই চলে যখন সাবজেক্টটি স্ক্রলপোর্টে প্রবেশ করে।

আপনি যে সম্ভাব্য ভিউ টাইমলাইন রেঞ্জগুলো টার্গেট করতে পারেন, সেগুলো হলো নিম্নরূপ:

  • cover : ভিউ প্রগ্রেস টাইমলাইনের সম্পূর্ণ পরিসরকে উপস্থাপন করে।
  • entry : এটি সেই পরিসরকে বোঝায়, যে সময়ে প্রিন্সিপাল বক্সটি ভিউ প্রগ্রেস ভিজিবিলিটি পরিসরে প্রবেশ করে।
  • exit : এটি সেই পরিসরকে বোঝায়, যার মধ্যে প্রধান বক্সটি ভিউ অগ্রগতির দৃশ্যমানতার পরিসর থেকে বেরিয়ে যায়।
  • entry-crossing : এটি সেই পরিসরকে বোঝায়, যে সময়ে প্রধান বক্সটি শেষ সীমানার কিনারা অতিক্রম করে।
  • exit-crossing : এটি সেই পরিসরকে বোঝায়, যার মধ্যে প্রধান বক্সটি প্রারম্ভিক সীমানার প্রান্ত অতিক্রম করে।
  • contain : এটি সেই পরিসরকে বোঝায়, যার মধ্যে প্রধান বক্সটি স্ক্রলপোর্টের অভ্যন্তরে তার ভিউ প্রোগ্রেস ভিজিবিলিটি পরিসরের দ্বারা সম্পূর্ণরূপে আবদ্ধ থাকে বা সেটিকে পুরোপুরি আবৃত করে। এটি নির্ভর করে সাবজেক্টটি স্ক্রলারের চেয়ে লম্বা না খাটো, তার উপর।

একটি রেঞ্জ নির্ধারণ করতে, আপনাকে অবশ্যই একটি রেঞ্জ-স্টার্ট এবং রেঞ্জ-এন্ড সেট করতে হবে। প্রতিটিতে একটি রেঞ্জ-নেম (উপরের তালিকা দেখুন) এবং সেই রেঞ্জ-নেমের মধ্যে অবস্থান নির্ধারণের জন্য একটি রেঞ্জ-অফসেট থাকে। রেঞ্জ-অফসেটটি সাধারণত 0% থেকে 100% পর্যন্ত একটি শতাংশ হয়, তবে আপনি 20em মতো একটি নির্দিষ্ট দৈর্ঘ্যও উল্লেখ করতে পারেন।

উদাহরণস্বরূপ, যদি আপনি কোনো ব্যক্তি প্রবেশ করার মুহূর্ত থেকে অ্যানিমেশনটি চালাতে চান, তাহলে রেঞ্জ-স্টার্ট হিসেবে entry 0% বেছে নিন। আর ব্যক্তিটি প্রবেশ করার আগেই অ্যানিমেশনটি শেষ করতে চাইলে, রেঞ্জ-এন্ডের মান হিসেবে entry 100% বেছে নিন।

CSS-এ, আপনি animation-range প্রপার্টি ব্যবহার করে এটি সেট করেন। উদাহরণ:

animation-range: entry 0% entry 100%;

জাভাস্ক্রিপ্টে rangeStart এবং rangeEnd প্রপার্টিগুলো ব্যবহার করুন।

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

প্রতিটি রেঞ্জ-নেম কী বোঝায় এবং পার্সেন্টেজগুলো কীভাবে শুরু ও শেষের অবস্থানকে প্রভাবিত করে, তা দেখতে নিচে দেওয়া টুলটি ব্যবহার করুন। রেঞ্জ-স্টার্টকে entry 0% এবং রেঞ্জ-এন্ডকে cover 50% এ সেট করার চেষ্টা করুন, এবং তারপর অ্যানিমেশনের ফলাফল দেখতে স্ক্রলবারটি ড্র্যাগ করুন।

ভিউ টাইমলাইন রেঞ্জেস ভিজ্যুয়ালাইজার, যা https://goo.gle/view-timeline-range-tool -এ উপলব্ধ।

একটি রেকর্ডিং দেখুন

এই ‘ভিউ টাইমলাইন রেঞ্জেস’ টুলটি ব্যবহার করার সময় আপনি হয়তো লক্ষ্য করবেন যে, কিছু রেঞ্জকে দুটি ভিন্ন রেঞ্জ-নাম + রেঞ্জ-অফসেট সংমিশ্রণ দ্বারা টার্গেট করা যায়। উদাহরণস্বরূপ, entry 0% , entry-crossing 0% , এবং cover 0% সবগুলোই একই এলাকাকে টার্গেট করে।

যখন রেঞ্জ-স্টার্ট এবং রেঞ্জ-এন্ড একই রেঞ্জ-নেমকে টার্গেট করে এবং সম্পূর্ণ রেঞ্জটি—০% থেকে ১০০% পর্যন্ত—জুড়ে থাকে, তখন আপনি ভ্যালুটিকে সংক্ষিপ্ত করে শুধু রেঞ্জের নামটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ, animation-range: entry 0% entry 100%; কে আরও সংক্ষিপ্ত করে animation-range: entry . আকারে লেখা যায়।

ডেমো: ছবি উন্মোচন

এই ডেমোটি স্ক্রলপোর্টে প্রবেশ করার সাথে সাথে ছবিগুলোকে ধীরে ধীরে দৃশ্যমান করে তোলে। এটি একটি অ্যানোনিমাস ভিউ টাইমলাইন ব্যবহার করে করা হয়। অ্যানিমেশনের পরিসরটি এমনভাবে সমন্বয় করা হয়েছে, যাতে প্রতিটি ছবি স্ক্রলারের মাঝামাঝি অবস্থানে থাকাকালীন সম্পূর্ণ অস্বচ্ছতা লাভ করে।

ডেমো: ছবি উন্মোচন

✨ নিজেই চেষ্টা করে দেখুন

একটি অ্যানিমেটেড ক্লিপ-পাথ ব্যবহার করে প্রসারণের প্রভাবটি আনা হয়।

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

CSS-এ একটি নামযুক্ত ভিউ প্রোগ্রেস টাইমলাইন তৈরি করা

স্ক্রল টাইমলাইনের যেমন নামযুক্ত সংস্করণ থাকে, ঠিক তেমনি আপনি নামযুক্ত ভিউ টাইমলাইনও তৈরি করতে পারেন। scroll-timeline-* প্রোপার্টিগুলোর পরিবর্তে আপনাকে view-timeline- প্রিফিক্সযুক্ত ভ্যারিয়েন্টগুলো ব্যবহার করতে হবে, যেমন view-timeline-name এবং view-timeline-axis

একই ধরনের মান প্রযোজ্য, এবং একটি নামযুক্ত টাইমলাইন খোঁজার ক্ষেত্রেও একই নিয়ম প্রযোজ্য।

ডেমো: চিত্র উন্মোচন, পুনঃপর্যালোচনা

আগের ইমেজ রিভিল ডেমোটি পুনরায় কাজ করার পর, সংশোধিত কোডটি দেখতে এইরকম:

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

view-timeline-name: revealing-image ব্যবহার করলে, এলিমেন্টটি তার নিকটতম স্ক্রলারের মধ্যে ট্র্যাক করা হবে। এরপর একই মান animation-timeline প্রপার্টির মান হিসেবে ব্যবহৃত হয়। এর ফলে ভিজ্যুয়াল আউটপুট আগের মতোই থাকে।

✨ নিজেই চেষ্টা করে দেখুন

জাভাস্ক্রিপ্টে একটি ভিউ প্রোগ্রেস টাইমলাইন তৈরি করা

জাভাস্ক্রিপ্টে একটি ভিউ টাইমলাইন তৈরি করতে, ViewTimeline ক্লাসের একটি নতুন ইনস্ট্যান্স তৈরি করুন। একটি প্রপার্টি ব্যাগে আপনি যে subject ট্র্যাক করতে চান, axis এবং inset পাস করুন।

  • subject : যে এলিমেন্টটিকে আপনি তার নিজস্ব স্ক্রলারের মধ্যে ট্র্যাক করতে চান, তার একটি রেফারেন্স।
  • axis : যে অক্ষটি অনুসরণ করতে হবে। CSS সংস্করণের মতোই, এখানে block , inline , x , এবং y মানগুলো গ্রহণযোগ্য।
  • inset : বক্সটি দেখা যাচ্ছে কিনা তা নির্ধারণ করার সময় স্ক্রলপোর্টের একটি ইনসেট (ধনাত্মক) বা আউটসেট (ঋণাত্মক) সমন্বয়।
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

এটিকে কোনো ওয়েব অ্যানিমেশনের সাথে যুক্ত করতে, timeline প্রপার্টি হিসেবে পাস করুন এবং কোনো duration থাকলে তা বাদ দিন। ঐচ্ছিকভাবে, rangeStart এবং rangeEnd প্রপার্টি ব্যবহার করে রেঞ্জের তথ্য পাস করুন।

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ নিজেই চেষ্টা করে দেখুন

আরও কিছু চেষ্টা করে দেখা যেতে পারে

এক সেট কীফ্রেম দিয়ে একাধিক ভিউ টাইমলাইন রেঞ্জে সংযুক্ত করা

চলুন এই কন্টাক্ট লিস্টের ডেমোটি দেখি, যেখানে লিস্টের এন্ট্রিগুলো অ্যানিমেটেড। যখন কোনো লিস্ট এন্ট্রি নিচ থেকে স্ক্রলপোর্টে প্রবেশ করে, তখন এটি স্লাইড করে ও ধীরে ধীরে ভেসে ওঠে, এবং যখন এটি ওপর থেকে স্ক্রলপোর্ট থেকে বেরিয়ে যায়, তখন এটি স্লাইড করে ও ধীরে ধীরে অদৃশ্য হয়ে যায়।

ডেমো: যোগাযোগের তালিকা

✨ নিজেই চেষ্টা করে দেখুন

এই ডেমোর জন্য, প্রতিটি এলিমেন্টকে একটি ভিউ টাইমলাইন দিয়ে সাজানো হয়েছে যা এলিমেন্টটির স্ক্রলপোর্ট অতিক্রম করার সময় সেটিকে ট্র্যাক করে, এবং এর সাথে দুটি স্ক্রল-চালিত অ্যানিমেশন যুক্ত করা হয়েছে। animate-in অ্যানিমেশনটি টাইমলাইনের entry রেঞ্জে এবং animate-out অ্যানিমেশনটি টাইমলাইনের exit রেঞ্জে যুক্ত করা হয়েছে।

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

দুটি ভিন্ন রেঞ্জের সাথে সংযুক্ত দুটি ভিন্ন অ্যানিমেশন চালানোর পরিবর্তে, এমন একটি কীফ্রেম সেট তৈরি করাও সম্ভব, যেটিতে আগে থেকেই রেঞ্জের তথ্য অন্তর্ভুক্ত থাকে।

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

যেহেতু কীফ্রেমগুলোতে রেঞ্জের তথ্য থাকে, তাই আপনার animation-range নির্দিষ্ট করার প্রয়োজন নেই। ফলাফল আগের মতোই হুবহু একই থাকবে।

✨ নিজেই চেষ্টা করে দেখুন

অ-পূর্বপুরুষ স্ক্রোল টাইমলাইনে সংযুক্ত করা

নেমড স্ক্রল টাইমলাইন এবং নেমড ভিউ টাইমলাইনের জন্য লুকআপ মেকানিজম শুধুমাত্র স্ক্রল অ্যানসেস্টরদের মধ্যেই সীমাবদ্ধ। তবে প্রায়শই, যে এলিমেন্টটিকে অ্যানিমেট করা প্রয়োজন, সেটি ট্র্যাক করার জন্য প্রয়োজনীয় স্ক্রলারের চাইল্ড হয় না।

এই কাজটি করার জন্য, timeline-scope প্রপার্টিটি কাজে আসে। আপনি এই প্রপার্টিটি ব্যবহার করে কোনো টাইমলাইন তৈরি না করেই সেই নামে একটি টাইমলাইন ঘোষণা করতে পারেন। এটি সেই নামের টাইমলাইনটিকে একটি বৃহত্তর পরিসর প্রদান করে। বাস্তবে, একটি শেয়ার্ড প্যারেন্ট এলিমেন্টে timeline-scope প্রপার্টিটি ব্যবহার করা হয়, যাতে একটি চাইল্ড স্ক্রলারের টাইমলাইন সেটির সাথে সংযুক্ত হতে পারে।

উদাহরণস্বরূপ:

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

এই অংশে:

  • .parent এলিমেন্টটি --tl নামে একটি টাইমলাইন ঘোষণা করে। এর যেকোনো চাইল্ড এলিমেন্ট এটিকে খুঁজে নিয়ে animation-timeline প্রপার্টির ভ্যালু হিসেবে ব্যবহার করতে পারে।
  • .scroller এলিমেন্টটি আসলে --tl নামের একটি স্ক্রল টাইমলাইন নির্ধারণ করে। ডিফল্টভাবে এটি শুধু এর চাইল্ড এলিমেন্টগুলোর কাছেই দৃশ্যমান হওয়ার কথা, কিন্তু যেহেতু .parent এটিকে scroll-timeline-root হিসেবে সেট করে রেখেছে, তাই এটি সেটির সাথে সংযুক্ত হয়ে যায়।
  • .subject এলিমেন্টটি --tl টাইমলাইন ব্যবহার করে। এটি তার পূর্বপুরুষ ট্রি-তে উপরের দিকে অগ্রসর হয় এবং .parent এ থাকা --tl খুঁজে বের করে। .parent এর --tl যেহেতু .scroller এর --tl কে নির্দেশ করে, তাই .subject মূলত .scroller এর স্ক্রল প্রোগ্রেস টাইমলাইনকে অনুসরণ করবে।

অন্যভাবে বললে, আপনি timeline-root ব্যবহার করে একটি টাইমলাইনকে তার পূর্বপুরুষের স্তরে উপরে সরাতে পারেন (যাকে হোইস্টিং বলা হয়), যাতে পূর্বপুরুষের সমস্ত চাইল্ড টাইমলাইন সেটিকে অ্যাক্সেস করতে পারে।

timeline-scope প্রপার্টিটি স্ক্রল টাইমলাইন এবং ভিউ টাইমলাইন উভয়ের সাথেই ব্যবহার করা যায়।

আরও ডেমো এবং রিসোর্স

এই নিবন্ধে আলোচিত সমস্ত ডেমো scroll-driven-animations.style মিনি-সাইটে রয়েছে। স্ক্রল-ড্রাইভেন অ্যানিমেশন দিয়ে কী কী করা সম্ভব, তা তুলে ধরতে ওয়েবসাইটটিতে আরও অনেক ডেমো অন্তর্ভুক্ত করা হয়েছে।

অতিরিক্ত ডেমোগুলোর মধ্যে একটি হলো অ্যালবাম কভারের এই তালিকাটি। প্রতিটি কভার ত্রিমাত্রিকভাবে ঘুরতে ঘুরতে কেন্দ্রবিন্দুতে চলে আসে।

ডেমো: কভার ফ্লো

✨ নিজেই চেষ্টা করে দেখুন

অথবা এই কার্ড স্ট্যাকিং ডেমোটি, যা ‘পজিশন position: sticky করে। কার্ডগুলো স্তূপ হওয়ার সাথে সাথে, আগে থেকে আটকে থাকা কার্ডগুলো ছোট হতে থাকে, যা একটি সুন্দর গভীরতার প্রভাব তৈরি করে। শেষে, পুরো স্তূপটি একসাথে দৃষ্টির বাইরে চলে যায়।

প্রদর্শন: কার্ড স্তূপ করা

✨ নিজেই চেষ্টা করে দেখুন

scroll-driven-animations.style- এ আরও কিছু টুল রয়েছে, যেমন View Timeline Range Progress ভিজ্যুয়ালাইজেশন, যা এই পোস্টের শুরুতে অন্তর্ভুক্ত করা হয়েছিল।

Google I/O '23-এর 'What's new in Web Animations' শীর্ষক প্রতিবেদনে স্ক্রল-চালিত অ্যানিমেশনগুলোও আলোচনা করা হয়েছে।