การควบคุมการเล่นภาพเคลื่อนไหวในเว็บใน Chrome 39

แซม โทโรกู๊ด
แซม โทโรกู๊ด

เมื่อต้นปีนี้ Chrome 36 ใช้เมธอดเอลิเมนต์ภาพเคลื่อนไหว ซึ่งเป็นส่วนหนึ่งของข้อกำหนดของเว็บแอนิเมชันในวงกว้าง ซึ่งช่วยเขียนภาพเคลื่อนไหวแบบเนทีฟที่มีประสิทธิภาพอย่างมีความจำเป็น ทำให้นักพัฒนาแอปสามารถเลือกสร้างภาพเคลื่อนไหวและการเปลี่ยนภาพด้วยวิธีที่เหมาะสมที่สุดสำหรับตน

สำหรับการทบทวนอย่างสั้นๆ วิธีการสร้างภาพเคลื่อนไหวของระบบคลาวด์บนหน้าจอโดยใช้การเรียกกลับเมื่อเสร็จสิ้นมีดังต่อไปนี้

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) อย่างไรก็ตาม มีกรณีพิเศษ 2 กรณีดังนี้

  • หากการเปลี่ยนแปลงที่เกิดจากเมธอด reverse() จะทำให้ภาพเคลื่อนไหวที่กำลังทำงานอยู่สิ้นสุดลงอย่างมีประสิทธิภาพ currentTime จะถูกกลับด้วย เช่น หากภาพเคลื่อนไหวใหม่เอี่ยม ภาพเคลื่อนไหวทั้งหมดจะเล่นถอยหลัง

  • หากโปรแกรมเล่นหยุดชั่วคราว ภาพเคลื่อนไหวจะเริ่มเล่น

การสครับโปรแกรมเล่น

ตอนนี้ AnimationPlayer อนุญาตให้แก้ไขcurrentTimeในระหว่างที่ภาพเคลื่อนไหวทำงานอยู่ โดยทั่วไปค่านี้จะเพิ่มขึ้นเมื่อเวลาผ่านไป (หรือลดลงหาก 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 เป็นขนาดที่ดาวน์โหลดในปัจจุบัน (การสาธิต)

การเปลี่ยน UI และท่าทางสัมผัส

แพลตฟอร์มมือถือเป็นอาณาจักรของท่าทางสัมผัสที่ใช้กันทั่วไปมาอย่างยาวนาน ไม่ว่าจะเป็นการลาก เลื่อน เลื่อน การปัด และอื่นๆ ท่าทางสัมผัสเหล่านี้มักจะมีธีมร่วมกัน นั่นคือ คอมโพเนนต์ UI ที่ลากได้ เช่น "การดึงเพื่อรีเฟรช" ของมุมมองรายการ หรือแถบด้านข้างมาจากด้านซ้ายของหน้าจอ

สำหรับภาพเคลื่อนไหวบนเว็บ เอฟเฟ็กต์ที่คล้ายกันนี้จะเกิดขึ้นบนเว็บได้ง่ายมาก ไม่ว่าจะในเดสก์ท็อปหรืออุปกรณ์เคลื่อนที่ เช่น เมื่อท่าทางสัมผัสที่ควบคุม 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 เสร็จสมบูรณ์แล้ว ฟีเจอร์และเอฟเฟกต์จะหายไป อย่างไรก็ตาม เวลาสุดท้ายจะตรงกับเวลาปัจจุบันของโปรแกรมเล่นที่ใช้งานอยู่ ดังนั้น UI ของคุณจะยังมีความสม่ำเสมอ

สุดท้าย ถ้าคุณชอบลูกแมว เรามีเว็บแอปพลิเคชันสำหรับสาธิตที่จะแสดงท่าทางสัมผัสเหล่านี้ ฟีเจอร์นี้เหมาะกับอุปกรณ์เคลื่อนที่และใช้ Polyfill สำหรับความเข้ากันได้แบบย้อนหลัง ดังนั้นให้ลองโหลดลงในอุปกรณ์เคลื่อนที่

เลื่อนไปที่เอลิเมนต์.animate

เมธอด element.animate มีประสิทธิภาพมากในขณะนี้ ไม่ว่าคุณจะใช้เมธอดนี้สำหรับภาพเคลื่อนไหวง่ายๆ หรือใช้ประโยชน์จาก AnimationPlayer ที่ส่งคืนมาด้วยวิธีอื่นๆ

ฟีเจอร์ทั้งสองนี้ยังได้รับการรองรับอย่างเต็มรูปแบบในเบราว์เซอร์รุ่นใหม่อื่นๆ ผ่าน Polyfill ขนาดเล็กด้วย Polyfill นี้จะตรวจหาฟีเจอร์ด้วย ดังนั้นเมื่อผู้ให้บริการเบราว์เซอร์มีข้อกำหนดเฉพาะ ฟีเจอร์นี้จึงจะทำงานได้เร็วและดีขึ้นเมื่อเวลาผ่านไป

นอกจากนี้ ข้อมูลจำเพาะของ Web Animations จะพัฒนาต่อไปเช่นกัน หากสนใจลองใช้ฟีเจอร์ใหม่ๆ ฟีเจอร์ดังกล่าวก็พร้อมให้บริการแล้วใน polyfill รายละเอียดเพิ่มเติม: web-animations-next