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

מוקדם יותר השנה, הוסיפה ל-Chrome 36 את השיטה element.animate כחלק מהמפרט הרחב יותר של Web Animations. כך אפשר ליצור אנימציות יעילות ונפוצות שנכתבות באופן אימפרטיבי – ומאפשר למפתחים ליצור את האנימציות והמעברים שלהם בשיטה המתאימה להם ביותר.

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

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() או להאזין לאירוע הסיום.

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

השהיה, חזרה אחורה או שינוי מהירות ההפעלה

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

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

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

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

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

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

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

בחירת מיקום בנגן

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

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

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 תקבל עדיפות על פני player. כשהערך של driftPlayer יסתיים, הוא וההשפעות שלו ייעלמו. עם זאת, השעה הסופית שלו תהיה זהה ל-currentTime של הנגן הבסיסי, כך שממשק המשתמש יישאר עקבי.

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

מעבר קדימה ו-Element.animate

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

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

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