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

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

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

תמיכה בדפדפן

  • Chrome: 115.
  • קצה: 115.
  • Firefox: מאחורי דגל.
  • Safari: לא נתמך.

מקור

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

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

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

התמונות בדף הזה עולות כאשר הן נראות.

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

  • דפדפנים מודרניים מבצעים גלילה בתהליך נפרד ולכן מספקים אירועי גלילה באופן אסינכרוני.
  • האנימציות של ה-thread הראשי כפופות ל-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. פעולה זו מטרגטת ביעילות את גלילה ברמה הבסיסית (root) כי היא הגלילה הקרובה ביותר של הרכיב #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 גם עם התכונה 'גלילה בציר הזמן' וגם עם 'הצגת צירי זמן'.

עוד הדגמות ומשאבים

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

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

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

✨ כדאי לנסות בעצמכם

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

הדגמה: ערימה של כרטיסים.

✨ כדאי לנסות בעצמכם

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

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