שיפורים בממשק ה-API של אנימציות באינטרנט ב-Chromium 84

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

תאריך פרסום: 27 במאי 2020

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

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

ב-Firefox וב-Safari כבר הטמיעו את כל התכונות של המפרט, אבל ב-Chromium 84 נוספו ל-Chrome ול-Edge הרבה תכונות שלא נתמכו קודם, שמאפשרות יכולת פעולה הדדית בין דפדפנים.

Web Animations API נוסף ל-Chromium לראשונה בגרסה 36, ביולי 2014. עכשיו המפרט יושלם בגרסה 84, שתושקה ביולי 2020.
ההיסטוריה הארוכה של Web Animations API ב-Chromium.

תחילת העבודה

אם השתמשתם בכללי @keyframe, יצירת אנימציה באמצעות Web Animations API אמורה להיות מוכרת לכם מאוד. קודם צריך ליצור אובייקט של פריים מפתח. זה יכול להיראות ככה ב-CSS:

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

ייראה כך כאן ב-JavaScript:

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

איפה מגדירים פרמטרים לאנימציה ב-CSS:

.modal {
  animation: openAnimation 1s 1 ease-in;
}

מגדירים ב-JS:

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

כמות הקוד היא בערך זהה, אבל עם JavaScript מקבלים כמה כוחות-על שלא קיימים ב-CSS בלבד. היכולות האלה כוללות את היכולת ליצור רצף של אפקטים ושליטה רבה יותר במצבי ההפעלה שלהם.

מעבר ל-element.animate()

עם זאת, בעקבות העדכון, Web Animations API כבר לא מוגבל לאנימציות שנוצרו באמצעות element.animate(). אנחנו יכולים גם לשנות אנימציות ומעברים ב-CSS.

getAnimations() היא שיטה שמחזירה את כל האנימציות ברכיב, ללא קשר לכך שהוא נוצר באמצעות element.animate() או באמצעות כללי CSS (אנימציה או מעבר ב-CSS). דוגמה למראה של הקוד:

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

איך לתזמור אנימציות באמצעות הבטחות (promises)

ב-Chromium 84 יש עכשיו שתי שיטות שאפשר להשתמש בהן עם הבטחות: animation.ready ו-animation.finished.

  • animation.ready מאפשרים לכם להמתין עד שהשינויים הממתינים ייכנסו לתוקף (כלומר, לעבור בין שיטות של בקרת הפעלה, כמו הפעלה והשהיה).
  • animation.finished מאפשר להריץ קוד JavaScript בהתאמה אישית כשהאנימציה מסתיימת.

ממשיכים עם הדוגמה שלנו ויוצרים שרשרת אנימציה מתואמת באמצעות animation.finished. כאן יש טרנספורמציה אנכית (scaleY), ואחריה טרנספורמציה אופקית (scaleX), ואחריה שינוי אטימות ברכיב צאצא:

החלת טרנספורמציות ואופקטים של אטימות על רכיב מודלי שנפתח. הדגמה ב-Codepen
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

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

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

דוגמה: הפעלה, השהיה וחזרה אחורה

מה שאפשר לפתוח, צריך לסגור! למרבה המזל, מאז גרסת Chromium 39, ממשק Web Animations API מאפשר לנו להפעיל, להשהות ולהפוך את האנימציות שלנו.

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

דוגמה לחלון דו-שיח שנפתח ונסגר בלחיצה על לחצן. לצפייה בהדגמה ב-Glitch

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

דוגמה: אינטראקציות דינמיות עם פריימים מרכזיים חלקיים

דוגמה לטירגוט מחדש, שבה לחיצה על העכבר משנה את האנימציה למיקום חדש. לצפייה בהדגמה ב-Glitch
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

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

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

שיפור הביצועים באמצעות אנימציות שניתן להחליף

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

כשהעכבר זז, מוצגת אנימציה של נתיב כוכב שביט. לצפייה בהדגמה ב-Glitch
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

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

  1. האנימציה מסתיימת.
  2. יש אנימציה אחת או יותר במקום גבוה יותר בסדר ההרכבה שגם היא הושלמה.
  3. האנימציות החדשות מאנימות את אותם מאפיינים.

כדי לראות בדיוק כמה אנימציות מוחלפות, אפשר לספור את כל האנימציות שהוסרו באמצעות מונה, ולהשתמש ב-anim.onremove כדי להפעיל את המונה.

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

  • animation.replaceState מאפשר לעקוב אחרי הסטטוס של אנימציה: פעיל, קבוע או מושעה.
  • animation.commitStyles() מעדכן את הסגנון של אלמנט על סמך הסגנון הבסיסי, יחד עם כל האנימציות של האלמנט בסדר המורכב.
  • animation.persist() מסמנת אנימציה כבלתי ניתנת להחלפה.

אנימציות חלקות יותר באמצעות מצבי שילוב

בעזרת Web Animations API, עכשיו אפשר להגדיר את המצב המשולב של האנימציות, כלומר הן יכולות להיות מצטברות או מצטברות, בנוסף למצב ברירת המחדל 'החלפה'. מצבי הרכבה מאפשרים למפתחים לכתוב אנימציות ייחודיות ולשלוט באופן שבו האפקטים משולבים. עכשיו יש תמיכה בשלושה מצבים מורכבים: 'replace' (מצב ברירת המחדל), 'add' ו-'accumulate'.

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

דגמה שמציגה את המצבים המשולבים 'ברירת מחדל', 'הוספה' ו'צבירה'. לצפייה בהדגמה ב-Glitch

במצב המורכב 'replace' שמוגדר כברירת מחדל, האנימציה הסופית מחליפה את מאפיין הטרנספורמציה ומסתיימת ב-rotate(360deg) scale(1.4). עבור 'add', הפונקציה composite מוסיפה את הסיבוב ומכפילה את הגודל, וכתוצאה מכך מתקבל המצב הסופי rotate(720deg) scale(1.96). 'accumulate' משלבת את הטרנספורמציות, וכתוצאה מכך מתקבל rotate(720deg) scale(1.8). מידע נוסף על המורכבות של המצבים המשולבים האלה זמין ברשימות המניחים CompositeOperation ו-CompositeOperationOrAuto במפרט של Web Animations.

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

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

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

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

מה צפוי בעתיד ל-Web Animations API

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