שליטה בהפעלה של אנימציות באינטרנט ב-Chrome 39

סאם ת'ורוגו
סאם ת'ורוגו

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

תזכורת קצרה:

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

זה לבדו ממש קל וכדאי לשקול את האפשרות הזו כחלק מארגז הכלים כאשר יוצרים אנימציות או מעברים באופן מיידי. עם זאת, ב-Chrome 39 נוספו תכונות של בקרת הפעלה לאובייקט AnimationPlayer שהוחזר על ידי element.animate. בעבר, אחרי יצירת אנימציה, הייתם יכולים להתקשר רק אל cancel() או להאזין לאירוע הסיום.

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

השהיה או החזרה לאחור או שינוי קצב ההפעלה

נתחיל בעדכון של הדוגמה שלמעלה כדי להשהות את האנימציה אם לוחצים על הענן:

cloud.addEventListener('mousedown', function() {
    player.pause();
});

אפשר גם לשנות את המאפיין playbackRate:

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

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

  • אם השינוי שנגרם על ידי השיטה reverse() גורם לאנימציה הרציפה להסתיים, פעולת ה-currentTime גם מתהפכת - למשל, אם אנימציה חדשה לגמרי הופכת, כל האנימציה מופעלת אחורה.

  • אם הנגן מושהה, האנימציה תתחיל לפעול.

קרצוף של השחקן

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

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

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

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

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

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

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

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

מעברים ותנועות בממשק המשתמש

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

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

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

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

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

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

המשך ו-Element.animate

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

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

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