פעם, הנפשה באינטרנט הייתה תחום השימוש של JavaScript, אבל ככל שהעולם עבר לנייד, ההנפשות עברו ל-CSS בגלל התחביר הדקלרטיבי והאופטימיזציות שהדפדפנים הצליחו לבצע בעזרתו. המטרה שלכם היא תמיד 60fps בנייד, ולכן מומלץ לא לחרוג ממה שדפדפנים יודעים להציג ביעילות.
יש יותר ויותר כלים שיעזרו לכם ליצור אנימציות יעילות יותר מבוססות-JavaScript, אבל הפתרון האולטימטיבי הוא איחוד של אנימציות מודעות ופרקטיות , שבהן ההחלטה איך לכתוב את האנימציות מבוססת על הקוד הברור ביותר, ולא על מה שאפשר לעשות בצורה אחת ולא בצורה השנייה.
אנימציות אינטרנט יכולות לענות על הקריאה הזו, והחלק הראשון שלהן הגיע ל-Chrome 36 בתור element.animate()
. הפונקציה החדשה הזו מאפשרת ליצור אנימציה ב-JavaScript בלבד ולהפעיל אותה ביעילות כמו כל אנימציה או מעבר של CSS (למעשה, החל מגרסה 34 של Chrome, אותו מנוע Web Animations מניע את כל השיטות האלה).
התחביר פשוט, והחלקים שלו אמורים להיות מוכרים לכם אם כתבתם פעם טרנזישן או אנימציה ב-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)';
המפתח נמצא בתגובה 'wait a frame'. כדי להתחיל את המעבר, הדפדפן צריך לאשר שהרכיב נמצא במיקום ההתחלה. יש כמה דרכים לעשות זאת. אחת מהדרכים הנפוצות ביותר היא לקרוא מאחד ממאפייני הרכיב שמאלצים את הדפדפן לחשב את הפריסה, וכך מוודאים שהוא יודע שלרכיב יש מיקום התחלה לפני המעבר למיקום הסיום. השיטה הזו מאפשרת לכם להרגיש טוב עם עצמכם על הידע המעמיק שלכם ברכיבים הפנימיים של הדפדפן, ועדיין להרגיש רע עם כל הקשה על המקלדת.
לעומת זאת, קריאה מקבילה ל-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, שחשיבותו הולכת וגדלה ככל שחלקים נוספים במפרט Web Animations מושקים. גם אנימציות שנוצרו באמצעות JavaScript וגם אנימציות שנוצרו באמצעות CSS יהיו עם נגני אנימציה משויכים, כך שאפשר יהיה לשלב אותן בצורה חלקה בדרכים מועילות ומעניינות.
עם זאת, בשלב הזה ל-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 של Web Animations, שמאפשר להשתמש בחלק גדול יותר מהמפרט המלא של Web Animations בכל אחד מהדפדפנים המודרניים והעדכניים.
יש דמו של אפקט השלג שאפשר לנסות גם בגרסה הילידים של element.animate()
וגם ב-polyfill.
דעתכם חשובה לנו
למעשה, זוהי תצוגה מקדימה של מה שעוד צפוי, והיא פורסמה במיוחד כדי לקבל משוב ממפתחים באופן מיידי. אנחנו עדיין לא בטוחים אם הגענו לכל תרחיש לדוגמה, או שטיפלנו בכל הבעיות בממשקי ה-API הקיימים ליצירת אנימציה. הדרך היחידה לדעת איך לעשות את זה בצורה נכונה היא שמפתחים ינסו את התכונה ויספרו לנו מה הם חושבים.
כמובן שאנחנו מקבלים בברכה תגובות לפוסט הזה, ותגובות לגבי התקן עצמו אפשר לשלוח לקבוצות העבודה של CSS ו-SVG דרך רשימת התפוצה public-fx.
עדכון, אוקטובר 2014: ב-Chrome 39 נוספה תמיכה בשיטות נוספות שקשורות לשליטה בהפעלה, כמו play()
, pause()
ו-reverse()
. הוא תומך גם בקפיצה לנקודה ספציפית בציר הזמן של אנימציה באמצעות המאפיין currentTime
. אתם יכולים לראות את הפונקציונליות הזו בפעולה בדמו החדש הזה.
תודה ל-Addy Osmani ול-Max Heinritz על העזרה ביצירת הפוסט הזה.