הנפשה של אלמנטים בזמן גלילה באמצעות אנימציות מבוססות גלילה

כאן תלמדו איך לעבוד עם צירי זמן לגלילה ולהציג צירי זמן כדי ליצור אנימציות מבוססות-גלילה באופן מוצהר.

אנימציות שמבוססות על גלילה

תמיכה בדפדפן

  • 115
  • 115
  • x

מקור

אנימציות המבוססות על גלילה הן דפוס חוויית משתמש נפוץ באינטרנט. אנימציה מבוססת גלילה מקושרת למיקום הגלילה של מאגר גלילה. המשמעות היא שכשגוללים למעלה או למטה, האנימציה המקושרת מחלצת קדימה או אחורה בתגובה ישירה. דוגמאות לכך הן אפקטים כמו תמונות רקע בצורת פרלקס או מחווני קריאה שנעים בזמן הגלילה.

אינדיקטור קריאה שמופיע בראש המסמך, שמופעל על ידי גלילה.

סוג דומה של אנימציה מבוססת גלילה הוא אנימציה שמקושרת למיקום של אלמנט בתוך מאגר הגלילה שלו. לדוגמה, רכיבים יכולים להתעמעם כשהם מופיעים.

התמונות בדף הזה הופכות לשקופות בהדרגה כשהן מופיעות.

הדרך הקלאסית ליצירת אפקטים כאלה היא להגיב לאירועי גלילה בשרשור הראשי, וזה מוביל לשתי בעיות עיקריות:

  • דפדפנים מודרניים מבצעים גלילה בתהליך נפרד, ולכן מספקים אירועי גלילה באופן אסינכרוני.
  • האנימציות בשרשור הראשי כפופות לבעיות בממשק (jank).

לכן קשה מאוד או קשה מאוד ליצור אנימציות מבוססות-גלילה שמניבות ביצועים טובים שמסתנכרנות עם גלילה.

החל מגרסה 115 של Chrome, יש קבוצה חדשה של ממשקי API ומושגים שבהם אפשר להשתמש כדי להפעיל אנימציות מוצהרות שמבוססות על גלילה: גלילה בצירי זמן והצגת צירי זמן.

הקונספטים החדשים האלה משתלבים עם הממשק הקיים Web Animations API (WAAPI) ו-CSS Animations API, וכך הם מקבלים את היתרונות שממשקי ה-API הקיימים האלה מעניקים. זה כולל את האפשרות להפעיל אנימציות שמבוססות על גלילה מה-thread הראשי. כן, לקרוא את המידע הזה נכון: עכשיו יכולות להיות לכם אנימציות חלקות במיוחד, שמופעלות על ידי גלילה, שבור מהשרשור הראשי, עם כמה שורות נוספות של קוד. מה לא מצא חן בעיניך?

אנימציות באינטרנט, סיכום קצר

אנימציות באינטרנט עם 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;
}

אנימציות באינטרנט עם JavaScript

ב-JavaScript, ניתן להשתמש ב-Web Animations API כדי להשיג בדיוק את אותם הדברים. אפשר לעשות זאת על ידי יצירת מופעים חדשים של Animation ו-KeyFrameEffect, או באמצעות השיטה Element animate() הקצרה יותר.

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

התוצאה החזותית הזו של קטע ה-JavaScript שלמעלה זהה לגרסת ה-CSS הקודמת.

צירי זמן של אנימציות

כברירת מחדל, אנימציה שמצורפת לרכיב פועלת בציר הזמן של המסמך. שעת המקור שלו מתחילה ב-0 כשהדף נטען, ומתחילה לתקתק קדימה עם התקדמות השעון. זהו ציר הזמן של האנימציה שמוגדר כברירת מחדל. עד עכשיו, הוא היה ציר הזמן היחיד של האנימציה שהייתה לך גישה אליו.

במפרט לאנימציות מבוססות-גלילה מוגדרים שני סוגים חדשים של צירי זמן שבהם ניתן להשתמש:

  • ציר הזמן להתקדמות בגלילה: ציר זמן שמקושר למיקום הגלילה של מאגר גלילה לאורך ציר מסוים.
  • הצגת ציר הזמן של ההתקדמות: ציר זמן שמקושר למיקום היחסי של רכיב מסוים במאגר הגלילה שלו.

גלילה בציר הזמן של ההתקדמות

ציר זמן להתקדמות בגלילה הוא ציר זמן של אנימציה שמקושר להתקדמות במיקום הגלילה של מאגר גלילה – שנקרא גם גלילה או גלילה – לאורך ציר מסוים. היא ממירה מיקום בטווח גלילה לאחוז התקדמות.

מיקום הגלילה ההתחלתי מייצג 0% התקדמות, ומיקום הגלילה הסופי מייצג 100% התקדמות. בתצוגה החזותית הבאה אפשר לראות שההתקדמות סופרת בין 0% ל-100% כשגוללים את פס הגלילה מלמעלה למטה.

הצגה חזותית של ציר הזמן של התקדמות הגלילה. כשגוללים למטה לחלק התחתון של פס הגלילה, הערך של ההתקדמות נספר למעלה מ-0% ל-100%.

✨ רוצה לנסות את זה בשביל עצמך?

לרוב, ציר הזמן של התקדמות הגלילה מופיע בצורה מקוצרת פשוט ל'גלילה בציר הזמן'.

הצגת ציר הזמן של ההתקדמות

סוג ציר הזמן הזה מקושר להתקדמות היחסית של רכיב מסוים בתוך מאגר גלילה. בדיוק כמו ציר זמן של התקדמות הגלילה, מתבצע מעקב אחר קיזוז הגלילה של גולל. בשונה מציר הזמן של התקדמות הגלילה, המיקום היחסי של נושא בתוך אותו גלילה הוא שקובע את ההתקדמות.

אפשר להשוות זאת לאופן הפעולה של IntersectionObserver, שבאמצעותו אפשר לעקוב אחר מידת החשיפה של רכיב מסוים בגלילה. אם הרכיב לא גלוי בסרגל הגלילה, הוא לא מצטלב. אם הוא גלוי בתוך פס הגלילה – גם החלק הקטן ביותר – הוא מצטלב.

ציר הזמן של ההתקדמות של הצפייה מתחיל ברגע שהנושא מתחיל להצטלב עם פס הגלילה ומסתיים כשהנושא מפסיק להצטלב עם פס הגלילה. בתצוגה החזותית הבאה, ניתן לראות שההתקדמות מתחילה מ-0% כשהנושא נכנס למאגר הגלילה ומגיע ל-100% ברגע שהנושא יצא ממאגר הגלילה.

הצגה חזותית של ציר הזמן של ההתקדמות. ההתקדמות נספרת מ-0% ל-100% כשהנושא (תיבה ירוקה) חוצה את פס הגלילה.

✨ רוצה לנסות את זה בשביל עצמך?

לעיתים קרובות, ציר הזמן של ההתקדמות של צפייה מופיע בצורה מקוצרת פשוט ל'הצגת ציר הזמן'. אפשר לטרגט חלקים ספציפיים בציר הזמן של ציר הזמן על סמך גודל הנושא, אבל פרטים נוספים על כך בהמשך.

איך להיות מעשיים עם צירי הזמן של התקדמות הגלילה

יצירת ציר זמן אנונימי של התקדמות גלילה ב-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 של מאגר הגלילה.

לדוגמה, כדי לקשר אנימציה לגורם הגלילה ברמה הבסיסית (root) בציר הבלוק, הערכים שיועברו אל scroll() הם root ו-block. יחד, הערך הוא scroll(root block).

הדגמה: אינדיקטור של התקדמות הקריאה

בהדגמה הזו יש אינדיקטור של התקדמות הקריאה קבוע בחלק העליון של אזור התצוגה. כשגוללים למטה בדף, סרגל ההתקדמות גדל עד שהוא תופס את רוחב אזור התצוגה המלא כשמגיעים לסוף המסמך. יצירת האנימציה מתבצעת באמצעות ציר זמן אנונימי של התקדמות הגלילה.

הדגמה: מחוון התקדמות הקריאה.

✨ רוצה לנסות את זה בשביל עצמך?

אינדיקטור התקדמות הקריאה ממוקם בראש הדף כשהמיקום קבוע. כדי להשתמש באנימציות מורכבות, לא מתבצעת אנימציה של width, אלא שהאלמנט מוקטן בציר ה-X באמצעות transform.

<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();
}

ציר הזמן של האנימציה grow-progress ברכיב #progress מוגדר לציר זמן אנונימי שנוצר באמצעות scroll(). לא ניתנים ארגומנטים ל-scroll() ולכן הוא יחזור לערכי ברירת המחדל.

פס הגלילה שמוגדר כברירת מחדל למעקב הוא nearest וציר ברירת המחדל הוא block. הפעולה הזו מטרגטת ביעילות את הכלי לגלילה ברמה הבסיסית, כי זו רכיב הגלילה הקרוב ביותר לרכיב #progress, תוך מעקב אחר כיוון הבלוק שלו.

יצירת ציר זמן בעל שם של התקדמות הגלילה ב-CSS

דרך חלופית להגדיר ציר זמן להתקדמות של גלילה היא להשתמש בציר זמן בעל שם. הוא קצת יותר ארוך, אבל הוא יכול להועיל לכם כשאתם לא מטרגטים לכלי גלילה ברמה העליונה או לתוכן ברמה הבסיסית (root), בדף נעשה שימוש במספר צירי זמן או כשלא פועלים חיפושים אוטומטיים. כך תוכלו לזהות את ציר הזמן של התקדמות הגלילה לפי השם שנתתם לו.

כדי ליצור ציר זמן של התקדמות הגלילה באלמנט, צריך להגדיר את מאפיין ה-CSS scroll-timeline-name במאגר הגלילה למזהה מתאים. הערך חייב להתחיל ב---.

כדי לשנות את הציר למעקב, צריך להצהיר גם על המאפיין scroll-timeline-axis. הערכים המותרים זהים לארגומנט <axis> של scroll().

לסיום, כדי לקשר את האנימציה לציר הזמן של התקדמות הגלילה, מגדירים את המאפיין 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-axis בקיצור scroll-timeline. למשל:

scroll-timeline: --my-scroller inline;

בהדגמה הזו מופיע אינדיקטור של שלב שמופיע מעל כל קרוסלת תמונות. כשקרוסלה מכילה שלוש תמונות, פס אינדיקטורים מתחיל ברוחב 33% כדי לציין שאתם מסתכלים כרגע בתמונה אחת מתוך שלוש. כשהתמונה האחרונה נמצאת בתצוגה – אפשר לקבוע על ידי בעל הגלילה שגלל לסוף – האינדיקטור תופס את כל רוחבו של הגלילה. כדי להפעיל את האנימציה נעשה שימוש בציר זמן של התקדמות הגלילה.

הדגמה: אינדיקטור צעדים בקרוסלה אופקית.

✨ רוצה לנסות את זה בשביל עצמך?

סימון הבסיס לגלריה הוא:

<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__progress ממוקם ממש בתוך רכיב ה-wrapper של .gallery. הגודל הראשוני שלו נקבע על ידי המאפיין המותאם אישית --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. הפעולה הזו מתבצעת באמצעות הפניה לציר הזמן של התקדמות הגלילה --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;
}

יצירת ציר זמן של התקדמות הגלילה באמצעות JavaScript

כדי ליצור ציר זמן לגלילה ב-JavaScript, יוצרים מופע חדש של המחלקה ScrollTimeline. יש להעביר את התיק עם המאפיין source ו-axis שאחריהם רוצים לעקוב.

  • source: הפניה לרכיב שאת הגלילה שלו רוצים לעקוב. משתמשים בפונקציה document.documentElement כדי לטרגט את הכלי לגלילה ברמה הבסיסית (root).
  • axis: קביעת הציר למעקב. בדומה לווריאציית ה-CSS, הערכים הקבילים הם block, inline, x ו-y.
const tl = new ScrollTimeline({
  source: document.documentElement,
});

כדי לצרף אותה לאנימציה באינטרנט, יש להעביר אותה כנכס timeline ולהשמיט את כל ה-duration אם יש כאלה.

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

הדגמה: אינדיקטור להתקדמות בקריאה, חזרת

כדי ליצור מחדש את האינדיקטור של התקדמות הקריאה באמצעות JavaScript, תוך שימוש באותם תגי עיצוב, צריך להשתמש בקוד JavaScript הבא:

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 שנוצר עוקב אחר הגלילה ברמה הבסיסית (root) ומשנה את קנה המידה של #progress בציר ה-X מ-0% ל-100% תוך כדי גלילה בדף.

✨ רוצה לנסות את זה בשביל עצמך?

איך להיות מעשיים עם הצגת ציר הזמן של ההתקדמות

יצירת ציר זמן של התקדמות צפייה אנונימית ב-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();
}

Intermezzo: הצגת טווחים של ציר הזמן

כברירת מחדל, אנימציה שמקושרת ל'הצגת ציר הזמן' מצורפת לכל טווח ציר הזמן. הקטע הזה מתחיל מהרגע שהאובייקט עומד להיכנס לחלונית הגלילה, ומסתיים כשהאובייקט יצא לגמרי מתיבת הגלילה.

אפשר גם לקשר את הדוח לחלק מסוים בציר הזמן של תצוגת ציר הזמן. כדי לעשות זאת, צריך לציין את הטווח שאליו רוצים לקשר אותו. לדוגמה, מצב כזה יכול לקרות רק כשהנושא נכנס לחלונית גלילה. בתצוגה החזותית הבאה, ההתקדמות של ספירה לאחור מ-0% כשהנושא נכנס למאגר הגלילה אבל כבר מגיע ל-100% מהרגע שבו הוא מצטלב לחלוטין.

תצוגת ציר הזמן מוגדרת למעקב אחר טווח ההרשמה של הנושא. האנימציה פועלת רק כשהמושא נכנס לחלונית הגלילה.

הטווחים האפשריים של הצגת ציר הזמן שניתן לטרגט הם:

  • cover: מייצג את הטווח המלא של התקדמות התצוגה.
  • entry: מייצג את הטווח שבו התיבה של חשבון המשתמש נכנסת לטווח החשיפה של התקדמות התצוגה.
  • exit: מייצג את הטווח שבו התיבה של המשתמש הראשי יוצאת מטווח החשיפה של התקדמות התצוגה.
  • entry-crossing: מייצג את הטווח שבו התיבה הראשית חוצה את קצה הגבול של הקצה.
  • exit-crossing: מייצג את הטווח שבו התיבה הראשית חוצה את קצה גבול ההתחלה.
  • contain: מייצג את הטווח שבו התיבה הראשית כלולה באופן מלא בטווח הניראות של ההתקדמות של התצוגה, או מכסה באופן מלא את טווח הגלילה בקטע הגלילה. זה תלוי בשאלה אם הנושא גבוה או קצר יותר מהגלילה.

כדי להגדיר טווח, עליך להגדיר תאריך התחלה וסיום של טווח. כל אחד מהם כולל שם טווח (ראו רשימה למעלה) וקיזוז טווח כדי לקבוע את המיקום בתוך שם הטווח. קיזוז הטווח הוא בדרך כלל אחוז שנע בין 0% ל-100%, אך ניתן גם לציין אורך קבוע כגון 20em.

לדוגמה, אם רוצים להריץ אנימציה מהרגע שהנושא נכנס, בוחרים entry 0% כנקודת ההתחלה של הטווח. כדי שהמשימה תסתיים עד שהנושא הזין, צריך לבחור ב-entry 100% כערך של סוף הטווח.

ב-CSS, מגדירים זאת באמצעות המאפיין animation-range. דוגמה:

animation-range: entry 0% entry 100%;

ב-JavaScript, יש להשתמש במאפיינים 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% מטרגטים לאותו אזור.

כאשר טווח ההתחלה וסוף הטווח מטרגטים לאותו שם טווח ונפרס על כל הטווח - מ-0% עד 100% - תוכל לקצר את הערך לשם פשוט לשם הטווח. לדוגמה, אפשר לשכתב את animation-range: entry 0% entry 100%; לanimation-range: entry הקצרה בהרבה.

הדגמה: חשיפת תמונה

סרטון ההדגמה הזה ילך וישתפר עם פתיחת הגלילה. הפעולה הזו מתבצעת באמצעות ציר זמן של תצוגה אנונימית. טווח האנימציה הותאם כך שכל תמונה תהיה באטימות מלאה כשהיא נמצאת בחצי מגלגל הגלילה.

הדגמה: חשיפת תמונות

✨ רוצה לנסות את זה בשביל עצמך?

ניתן להשיג את אפקט ההרחבה באמצעות נתיב קליפ מונפש. זה ה-CSS שמשמש את האפקט הזה:

@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. הפלט הוויזואלי בדיוק כמו קודם.

✨ רוצה לנסות את זה בשביל עצמך?

יצירת ציר זמן של התקדמות צפייה ב-JavaScript

כדי ליצור הצגת ציר זמן ב-JavaScript, צריך ליצור מופע חדש של המחלקה 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. הוא הולך במעלה עץ אבותיו ומוצא --tl על ה.parent. כאשר --tl ב-.parent מצביע על --tl של .scroller, .subject למעשה יעקוב אחר ציר הזמן של התקדמות הגלילה ב-.scroller.

אפשר להגיד אחרת, אפשר להשתמש ב-timeline-root כדי להעביר ציר זמן למעלה לאב אב (שנקרא עלייה), כדי שכל הצאצאים של ישות האב יוכלו לגשת אליו.

אפשר להשתמש בנכס timeline-scope גם עם גלילה בצירי זמן וגם עם הצגת צירי זמן.

עוד הדגמות ומקורות מידע

כל ההדגמות שמתוארות במאמר הזה בנושא המיני-אתר Scroll-driven-animations.style. האתר כולל עוד הדגמות רבות שמדגישות את מה שאפשר לעשות עם אנימציות מבוססות גלילה.

אחת מההדגמות הנוספות היא רשימת עטיפות האלבומים. כל כריכה מסתובבת בתלת-ממד כשהיא לוקחת את הזרקור במרכז.

הדגמה: תהליך כיסוי

✨ רוצה לנסות את זה בשביל עצמך?

או להדגמת הערימה של קלפים שמשתמשים ב-position: sticky. ככל שהקלפים מוערמות, הכרטיסים שכבר נתקעו מתרחבים ויוצרים אפקט עומק נחמד. בסוף, כל המקבץ יישלש מהתמונה כקבוצה.

הדגמה: סידור קלפים.

✨ רוצה לנסות את זה בשביל עצמך?

מופיע גם ב- scroll-driven-animations.style אוסף של כלים כמו ההמחשה החזותית 'הצגת ההתקדמות של טווח ציר הזמן' שנכללה קודם בפוסט הזה.

גם אנימציות המונעות גלילה מופיעות במאמר מה חדש באנימציות באינטרנט ב-Google I/O 2023.