با انیمیشن های اسکرول در CSS شروع کنید

1. قبل از شروع

انیمیشن‌های اسکرول‌مدار به شما این امکان را می‌دهند که پخش یک انیمیشن را بر اساس موقعیت اسکرول ظرف اسکرول کنترل کنید. این به این معنی است که با اسکرول کردن به سمت بالا یا پایین، انیمیشن به جلو یا عقب می رود. علاوه بر این، با انیمیشن‌های پیمایشی، می‌توانید انیمیشن را بر اساس موقعیت یک عنصر در ظرف اسکرول آن کنترل کنید. این به شما امکان می‌دهد جلوه‌های جالبی مانند تصویر پس‌زمینه اختلاف منظر، نوارهای پیشرفت اسکرول و تصاویری ایجاد کنید که در هنگام مشاهده، خود را نشان می‌دهند.

جدید در کروم 115 پشتیبانی از مجموعه‌ای از کلاس‌های جاوا اسکریپت و ویژگی‌های CSS است که به شما امکان می‌دهد به راحتی انیمیشن‌های پیمایش محور را ایجاد کنید. این APIهای جدید در ارتباط با Web Animations و CSS Animations APIهای موجود کار می کنند.

این کد لبه به شما یاد می دهد که چگونه با استفاده از CSS انیمیشن های اسکرول را ایجاد کنید. با تکمیل این کد لبه، با بسیاری از ویژگی‌های جدید CSS که توسط این ویژگی هیجان‌انگیز معرفی شده‌اند، آشنا می‌شوید، مانند scroll-timeline ، view-timeline ، animation-timeline و animation-range .

چیزی که یاد خواهید گرفت

  • نحوه ایجاد افکت پس‌زمینه اختلاف منظر با Scroll Timeline در CSS.
  • نحوه ایجاد نوار پیشرفت با Scroll Timeline در CSS.
  • نحوه ایجاد افکت آشکارسازی تصویر با View Timeline در CSS.
  • نحوه هدف‌گیری انواع مختلف محدوده‌های View Timeline در CSS.

آنچه شما نیاز دارید

یکی از ترکیب دستگاه های زیر:

  • نسخه اخیر Chrome (115 یا بالاتر) در ChromeOS، macOS، یا Windows با پرچم «ویژگی‌های پلتفرم وب آزمایشی» روی فعال تنظیم شده است.
  • درک اولیه HTML
  • درک اساسی از CSS، به ویژه انیمیشن ها در CSS

2. راه اندازی شوید

هر آنچه برای این پروژه نیاز دارید در مخزن GitHub موجود است. برای شروع، کد را شبیه سازی کنید و آن را در محیط برنامه نویس مورد علاقه خود باز کنید.

  1. یک برگه مرورگر جدید باز کنید و به https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab بروید.
  2. مخزن را شبیه سازی کنید.
  3. کد را در IDE دلخواه خود باز کنید.
  4. npm install برای نصب وابستگی ها اجرا کنید.
  5. npm start اجرا کنید و به http://localhost:3000/ مراجعه کنید.
  6. از طرف دیگر، اگر npm را نصب نکرده‌اید، فایل src/index.html را در کروم باز کنید.

3. در مورد جدول زمانی انیمیشن بیاموزید

به طور پیش فرض، یک انیمیشن متصل به یک عنصر در خط زمانی سند اجرا می شود. این بدان معنی است که وقتی صفحه بارگذاری می شود، انیمیشن با گذشت زمان به جلو حرکت می کند. این جدول زمانی پیش‌فرض انیمیشن است و تاکنون تنها خط زمانی انیمیشنی بود که به آن دسترسی داشتید.

با انیمیشن های پیمایشی، به دو نوع جدید از جدول زمانی دسترسی پیدا می کنید:

  • جدول زمانی پیشرفت را پیمایش کنید
  • مشاهده جدول زمانی پیشرفت

در CSS، این خطوط زمانی را می توان با استفاده از ویژگی animation-timeline به یک انیمیشن متصل کرد. به معنای این خطوط زمانی جدید و تفاوت آنها با یکدیگر نگاه کنید.

جدول زمانی پیشرفت را پیمایش کنید

جدول زمانی پیشرفت پیمایش یک جدول زمانی انیمیشن است که به پیشرفت در موقعیت اسکرول محفظه اسکرول - همچنین به نام اسکرولپورت یا اسکرولر - در امتداد یک محور خاص مرتبط است. این یک موقعیت در محدوده پیمایش را به درصد پیشرفت در طول یک جدول زمانی تبدیل می کند.

موقعیت اسکرول شروع نشان دهنده 0٪ پیشرفت و موقعیت اسکرول پایانی نشان دهنده 100٪ پیشرفت است. در تجسم زیر، توجه داشته باشید که با اسکرول کردن به پایین، پیشرفت از 0٪ تا 100٪ افزایش می یابد.

مشاهده جدول زمانی پیشرفت

این نوع جدول زمانی به پیشرفت نسبی یک عنصر خاص در یک ظرف اسکرول مرتبط است. درست مانند جدول زمانی پیشرفت اسکرول، افست اسکرول پیمایش ردیابی می شود. برخلاف جدول زمانی پیشرفت پیمایش، موقعیت نسبی سوژه در آن پیش‌گرد است که پیشرفت را تعیین می‌کند. این قابل مقایسه با IntersectionObserver است که میزان قابل مشاهده بودن یک عنصر در اسکرول را ردیابی می کند. اگر عنصر در اسکرول قابل مشاهده نباشد، متقاطع نیست. اگر در داخل اسکرول قابل مشاهده باشد – حتی برای کوچکترین قسمت – متقاطع است.

جدول زمانی نمایش پیشرفت از لحظه ای شروع می شود که سوژه شروع به تقاطع با پیمایش می کند و زمانی پایان می یابد که موضوع از تقاطع آن با پیمایش متوقف شود. در تصویرسازی زیر، توجه داشته باشید که زمانی که سوژه وارد محفظه اسکرول می‌شود، پیشرفت از 0 درصد شروع به شمارش می‌کند و تا زمانی که از ظرف اسکرول خارج می‌شود به 100 درصد می‌رسد.

به‌طور پیش‌فرض، یک انیمیشن مرتبط با جدول زمانی View Progress به کل محدوده آن متصل می‌شود. این از لحظه ای که سوژه وارد اسکرولپورت می شود شروع می شود و با خروج سوژه از اسکرولپورت به پایان می رسد.

همچنین می توان با تعیین محدوده ای که باید به آن متصل شود، آن را به بخش خاصی از جدول زمانی نمایش پیشرفت پیوند داد. این می تواند، برای مثال، تنها زمانی باشد که سوژه در حال ورود به اسکرولر باشد. در تصویرسازی زیر، زمانی که سوژه وارد محفظه اسکرول می‌شود، پیشرفت از 0 درصد شروع به شمارش می‌کند، اما از لحظه‌ای که کاملاً قطع می‌شود به 100 درصد می‌رسد.

محدوده‌های ممکن View Timeline که می‌توانید هدف قرار دهید عبارتند از: cover ، contain ، entry ، exit ، entry-crossing ، و exit-crossing . این محدوده‌ها بعداً در این آزمایشگاه کد توضیح داده شده‌اند، اما اگر نمی‌توانید منتظر بمانید تا بدانید، از ابزار واقع در https://goo.gle/view-timeline-range-tool استفاده کنید تا ببینید هر محدوده چه چیزی را نشان می‌دهد.

4. یک افکت پس زمینه اختلاف منظر ایجاد کنید

اولین افکتی که به صفحه اضافه می شود افکت پس زمینه اختلاف منظر روی تصویر پس زمینه اصلی است. همانطور که صفحه را به پایین اسکرول می کنید، تصویر پس زمینه باید حرکت کند، هرچند با سرعت متفاوت. برای این کار، به یک جدول زمانی پیشرفت پیمایش تکیه می کنید.

برای اجرای این امر دو مرحله وجود دارد:

  1. انیمیشنی ایجاد کنید که موقعیت تصویر پس زمینه را جابجا کند.
  2. انیمیشن را به پیشرفت پیمایش سند پیوند دهید.

انیمیشن را ایجاد کنید

  1. برای ایجاد انیمیشن، از مجموعه‌ای از فریم‌های کلیدی معمولی استفاده کنید. در آن، موقعیت پس زمینه را از 0% به صورت عمودی به 100% منتقل کنید:

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. اکنون این فریم های کلیدی را به عنصر بدنه وصل کنید:

src/styles.css

body {
  animation: 1s linear move-background;
}

با این کد انیمیشن move-background به عنصر بدنه اضافه می شود. ویژگی animation-duration آن روی یک ثانیه تنظیم شده است و از یک کاهش linear استفاده می کند.

ساده ترین راه برای ایجاد جدول زمانی Scroll Progress استفاده از تابع scroll() است. این یک جدول زمانی پیشرفت پیمایش ناشناس ایجاد می کند که می توانید آن را به عنوان مقدار ویژگی animation-timeline تنظیم کنید.

تابع scroll() یک آرگومان <scroller> و <axis> را می پذیرد.

مقادیر پذیرفته شده برای آرگومان <scroller> به شرح زیر است:

  • nearest . از نزدیکترین محفظه اسکرول اجداد (پیش‌فرض) استفاده می‌کند.
  • root . از نمای سند به عنوان محفظه اسکرول استفاده می کند.
  • self . از خود عنصر به عنوان محفظه اسکرول استفاده می کند.

مقادیر پذیرفته شده برای آرگومان <axis> به شرح زیر است:

  • block . از اندازه گیری پیشرفت در امتداد محور بلوک ظرف اسکرول (پیش فرض) استفاده می کند.
  • inline . از اندازه گیری پیشرفت در امتداد محور درونی ظرف اسکرول استفاده می کند.
  • y از اندازه گیری پیشرفت در امتداد محور y ظرف اسکرول استفاده می کند.
  • x از اندازه گیری پیشرفت در امتداد محور x ظرف اسکرول استفاده می کند.

برای پیوند دادن انیمیشن به پیمایش ریشه در محور بلوک، مقادیری که باید به scroll() منتقل شوند root و block هستند. با هم، مقدار scroll(root block) است.

  • scroll(root block) را به عنوان مقدار خاصیت animation-timeline روی بدنه تنظیم کنید.
  • علاوه بر این، از آنجایی که animation-duration بیان شده در ثانیه معنی ندارد، مدت زمان را روی auto تنظیم کنید. اگر animation-duration مشخص نکنید، به طور پیش‌فرض روی auto خواهد بود.

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

از آنجایی که پیمایش ریشه نزدیک‌ترین پیمایش والد عنصر بدنه است، می‌توانید از مقدار nearest نیز استفاده کنید:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

از آنجا که nearest و block مقادیر پیش‌فرض هستند، حتی می‌توانید آنها را حذف کنید. در این صورت، کد را می توان به این شکل ساده کرد:

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

تغییرات خود را تأیید کنید

اگر همه چیز خوب پیش رفت، اکنون باید این را داشته باشید:

در غیر این صورت، به بخش solution-step-1 کد مراجعه کنید.

5. یک نوار پیشرفت برای گالری تصاویر ایجاد کنید

در صفحه یک چرخ فلک افقی وجود دارد که به نوار پیشرفت نیاز دارد تا نشان دهد در حال حاضر کدام عکس را مشاهده می کنید.

نشانه گذاری برای چرخ فلک به صورت زیر است:

src/index.html

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

فریم های کلیدی برای نوار پیشرفت در حال حاضر در محل قرار دارند و به شکل زیر هستند:

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

این انیمیشن باید به ضمیمه شود. عنصر gallery__progress با جدول زمانی پیشرفت پیمایش. همانطور که در مرحله قبل نشان داده شد، می توانید با ایجاد یک جدول زمانی پیشرفت اسکرول ناشناس با تابع scroll() به این مهم دست یابید:

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

در حالی که این قطعه کد ممکن است به نظر کار می‌آید، اما به دلیل نحوه جستجوی خودکار ظرف اسکرول با استفاده از nearest کار نیست. هنگام جستجوی نزدیکترین اسکرول، عنصر فقط عناصری را در نظر می گیرد که می توانند بر موقعیت آن تأثیر بگذارند. از آنجایی که .gallery__progress کاملاً در موقعیت قرار دارد، اولین عنصر والد که موقعیت آن را تعیین می کند، عنصر .gallery است زیرا position: relative اعمال شده دارد. این بدان معنی است که عنصر .gallery__scrollcontainer – که پیمایشی است که باید مورد هدف قرار گیرد – در طول این جستجوی خودکار اصلا در نظر گرفته نمی شود.

برای حل این مشکل، در عنصر .gallery__scrollcontainer یک Scroll Progress Timeline با نام Scroll Progress ایجاد کنید و .gallery__progress را با استفاده از آن نام به آن پیوند دهید.

برای ایجاد یک جدول زمانی پیشرفت اسکرول با نام روی یک عنصر، ویژگی scroll-timeline-name CSS را در ظرف اسکرول روی مقدار دلخواه خود تنظیم کنید. مقدار باید با -- شروع شود.

از آنجایی که گالری به صورت افقی اسکرول می شود، باید ویژگی scroll-timeline-axis نیز تنظیم کنید. مقادیر مجاز همان آرگومان <axis> scroll() است.

در نهایت، برای پیوند دادن انیمیشن به جدول زمانی Scroll Progress، ویژگی animation-timeline را روی عنصری که باید متحرک شود، با همان مقدار شناسه استفاده شده برای scroll-timeline-name تنظیم کنید.

  • فایل styles.css را با موارد زیر تغییر دهید:

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: --gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: --gallery-is-scrolling;
}

تغییرات خود را تأیید کنید

اگر همه چیز خوب پیش رفت، اکنون باید این را داشته باشید:

در غیر این صورت، به بخش solution-step-2 کد مراجعه کنید.

6. تصاویر گالری را هنگام ورود و خروج از اسکرولپورت متحرک کنید

یک جدول زمانی نمایش پیشرفت ناشناس تنظیم کنید

یک جلوه خوب برای افزودن این است که در هنگام مشاهده تصاویر در گالری محو شوند. برای این کار، می توانید از جدول زمانی نمایش پیشرفت استفاده کنید.

برای ایجاد جدول زمانی View Progress، می توانید از تابع view() استفاده کنید. آرگومان های پذیرفته شده آن <axis> و <view-timeline-inset> هستند.

  • <axis> مانند جدول زمانی پیشرفت پیمایش است و مشخص می کند که کدام محور را ردیابی کند.
  • با <view-timeline-inset> ، می‌توانید یک افست (مثبت یا منفی) را برای تنظیم کران‌ها در زمانی که عنصری در نظر گرفته می‌شود در نظر گرفته می‌شود مشخص کنید.
  • فریم های کلیدی از قبل در جای خود قرار دارند، بنابراین فقط باید آنها را وصل کنید. برای انجام این کار، روی هر عنصر .gallery__entry یک جدول زمانی مشاهده پیشرفت ایجاد کنید.

src/styles.css

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

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

محدوده زمانی نمایش پیشرفت را محدود کنید

اگر CSS را ذخیره کنید و صفحه را بارگذاری کنید، می بینید که عناصر محو می شوند، اما چیزی به نظر می رسد. زمانی که کاملاً خارج از دید هستند با کدورت 0 شروع می‌شوند و زمانی که کاملاً خارج شده‌اند به کدورت 1 ختم می‌شوند.

این به این دلیل است که محدوده پیش‌فرض برای یک جدول زمانی نمایش پیشرفت، محدوده کامل است. این به عنوان محدوده cover شناخته می شود.

  1. برای هدف قرار دادن فقط محدوده entry موضوع، از ویژگی CSS animation-range استفاده کنید تا زمان اجرای انیمیشن را محدود کنید.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

انیمیشن اکنون از entry 0% (سوژه در شرف ورود به اسکرولر) تا entry 100% اجرا می شود (موضوع به طور کامل وارد پیمایش شده است).

محدوده‌های نمایش زمانی ممکن به شرح زیر است:

  • cover . محدوده کامل جدول زمانی پیشرفت نمایش را نشان می دهد.
  • entry . نشان دهنده محدوده ای است که در طی آن کادر اصلی وارد محدوده دید پیشرفت نما می شود.
  • exit . محدوده ای را نشان می دهد که در طی آن کادر اصلی از محدوده دید پیشرفت نما خارج می شود.
  • entry-crossing . محدوده ای را نشان می دهد که در طی آن جعبه اصلی از لبه مرزی انتهایی عبور می کند.
  • exit-crossing . نشان دهنده محدوده ای است که در طی آن جعبه اصلی از لبه مرز شروع عبور می کند.
  • contain . محدوده‌ای را نشان می‌دهد که در طی آن کادر اصلی یا به‌طور کامل توسط محدوده دید پیشرفت نمای آن در اسکرولپورت قرار می‌گیرد یا کاملاً پوشش می‌دهد. این بستگی به این دارد که آیا سوژه بلندتر یا کوتاهتر از اسکرولر باشد.

از ابزار واقع در https://goo.gle/view-timeline-range-tool استفاده کنید تا ببینید هر محدوده نشان دهنده چیست و چگونه درصدها بر موقعیت های شروع و پایان تأثیر می گذارد.

  1. از آنجا که محدوده شروع و پایان در اینجا یکسان است و از افست های پیش فرض استفاده می شود، animation-range به یک نام محدوده انیمیشن ساده کنید:

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • برای محو کردن تصاویر در هنگام خروج از اسکرول، می‌توانید مانند انیمیشن انیمه‌ای انجام دهید، اما محدوده متفاوتی را هدف قرار دهید.

src/styles.css

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

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

فریم‌های کلیدی animate-in محدوده entry و فریم‌های کلیدی animate-out در محدوده exit اعمال خواهند شد.

تغییرات خود را تأیید کنید

اگر همه چیز خوب پیش رفت، اکنون باید این را داشته باشید:

در غیر این صورت، بخش solution-step-3 کد را بررسی کنید.

7. تصاویر گالری را هنگام ورود و خروج از اسکرولپورت با استفاده از یک مجموعه از فریم های کلیدی متحرک کنید.

مورد برای یک مجموعه از فریم های کلیدی

به جای اتصال دو انیمیشن به محدوده های مختلف، می توان یک مجموعه از فریم های کلیدی ایجاد کرد که از قبل حاوی اطلاعات محدوده باشد.

شکل فریم های کلیدی به این صورت است:

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. فریم های کلیدی fade-in و fade-out را به این صورت ترکیب کنید:

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. وقتی اطلاعات محدوده در فریم‌های کلیدی وجود دارد، دیگر نیازی نیست که animation-range جداگانه مشخص کنید. فریم های کلیدی را به عنوان ویژگی animation ضمیمه کنید.

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

تغییرات خود را تأیید کنید

اگر همه چیز خوب پیش رفت، باید همان نتیجه مرحله قبل را داشته باشید. در غیر این صورت، به بخش solution-step-4 کد مراجعه کنید.

8. تبریک می گویم!

شما این کد را به پایان رساندید و اکنون می دانید که چگونه جدول زمانی پیشرفت اسکرول را ایجاد کنید و خطوط زمانی پیشرفت را در CSS مشاهده کنید!

بیشتر بدانید

منابع: