אנימציות באינטרנט – Element.animate() זמינות עכשיו ב-Chrome 36

ברנדן קני
ברנדן קני

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

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

אנימציות באינטרנט מופיעות כמענה לשיחה, והחלק הראשון שלה נחת ב-Chrome 36 בצורת element.animate(). הפונקציה החדשה מאפשרת ליצור אנימציה אך ורק ב-JavaScript, ולהפעיל אותה באותה יעילות כמו כל אנימציה או מעבר של CSS (למעשה, החל מגרסה 34 של Chrome, אותו מנוע של 'אנימציות באינטרנט' פועל בכל השיטות האלה).

התחביר פשוט, וחלקים שלו אמורים להיות מוכרים לכם אם אי פעם כתבתם העברת CSS או אנימציה:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

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

לדוגמה, עבור Santa tracker בשנה שעברה, רצינו שיירד שלג כל הזמן, והחלטנו להנפיש אותו באמצעות CSS כדי שניתן יהיה לבצע אותו בצורה כל כך יעילה.

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

לכן נקטנו את הגישה הבאה, שאמורה להיות מוכרת:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

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

לעומת זאת, הקריאה המקבילה ל-element.animate() לא ברורה יותר, ואומרת בדיוק למה התכוונת:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

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

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

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

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

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

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

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

אני רוצה לנסות

כל אלה כוללים משלוחים ב-Chrome 36, וממשיכים לגרסת הבטא היום! אם ברצונך לנסות אותה, אפשר לנסות לעבוד עם ההטמעה המקורית ב-Chrome 36. עם זאת, יש polyfill של אנימציות באינטרנט, שמביא חלק גדול בהרבה מהמפרט המלא של אנימציות באינטרנט לכל אחד מהדפדפנים המודרניים האלה.

יש לך הדגמה של אפקט השלג כדי לנסות להשתמש גם בגרסה המקורית של element.animate() וגם ב-polyfill.

דעתכם חשובה לנו

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

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

עדכון, אוקטובר 2014: הוספנו ב-Chrome 39 תמיכה בכמה שיטות נוספות הקשורות לשליטה בהפעלה, כגון play(), pause() ו-reverse(). התכונה הזו גם תומכת בקפיצה לנקודה ספציפית בציר הזמן של אנימציה דרך המאפיין currentTime. אפשר לראות את הפונקציונליות הזו בפעולה בהדגמה החדשה הזו.

תודה לאדי אוסמאני ולמקס היינרץ על העזרה בפוסט הזה.