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

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

Kevin Ellis
Kevin Ellis

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

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

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

ב-Firefox וב-Safari כבר הטמיעו את כל התכונות של המפרט, אבל בגרסה 84 של Chromium נוספו ל-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 של המעבר כדי לקבוע מאיפה אנחנו עוברים. לאחר מכן יוצרים שתי אנימציות חדשות של שקיפות, ומאפשרות את אפקט העמעום הדרגתי. בסיום המעבר, מוחקים את העותק.

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

ב-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(). כך תוכלו ליצור אינטראקציה חלקה יותר ומותאמת יותר להקשר של חלון הדו-שיח שלנו.

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

אפשר ליצור שתי אנימציות בהמתנה להפעלה (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.

הנה דוגמה לרכיב ממשק משתמש:

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

כאן מוצגות שתי אנימציות 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

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