ภาพเคลื่อนไหวบนเว็บ - ขณะนี้เอลิเมนต์.animate() อยู่ใน Chrome 36 แล้ว

ภาพเคลื่อนไหวบนเว็บเคยเป็นขอบเขตของ JavaScript แต่เมื่อโลกหันมาใช้อุปกรณ์เคลื่อนที่ ภาพเคลื่อนไหวก็ย้ายไปอยู่ใน CSS เพื่อใช้ไวยากรณ์แบบประกาศและการเพิ่มประสิทธิภาพที่เบราว์เซอร์ทำได้ เมื่อเป้าหมายของคุณคือ 60 fps บนอุปกรณ์เคลื่อนที่เสมอ คุณจึงไม่ควรใช้สิ่งที่เบราว์เซอร์แสดงได้อย่างมีประสิทธิภาพ

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

ภาพเคลื่อนไหวบนเว็บพร้อมที่จะตอบสนองต่อความต้องการดังกล่าว และส่วนแรกได้เปิดตัวใน Chrome 36 ในรูปแบบ element.animate() แล้ว ฟังก์ชันใหม่นี้ช่วยให้คุณสร้างภาพเคลื่อนไหวใน JavaScript ได้อย่างสมบูรณ์และทำงานได้อย่างมีประสิทธิภาพเทียบเท่ากับภาพเคลื่อนไหวหรือการเปลี่ยน CSS (อันที่จริงแล้ว ตั้งแต่ Chrome 34 เครื่องมือ Web Animation เดียวกันนี้ขับเคลื่อนวิธีการทั้งหมดเหล่านี้)

รูปแบบคำสั่งนั้นง่ายมาก และคุณน่าจะคุ้นเคยกับส่วนต่างๆ ของมันหากเคยเขียนทรานซิชันหรือภาพเคลื่อนไหว 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)';

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

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

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 อย่างไรก็ตาม มี Web Animations polyfill ซึ่งจะนําข้อกําหนด Web Animations ฉบับเต็มมาใช้กับเบราว์เซอร์สมัยใหม่แบบใช้งานได้ตลอด

คุณสามารถลองใช้เอฟเฟกต์หิมะใน element.animate() เวอร์ชันเนทีฟและ polyfill ได้ในหน้าตัวอย่าง

บอกให้เรารู้ว่าคุณคิดอย่างไร

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

ความคิดเห็นในโพสต์นี้มีประโยชน์อย่างยิ่ง และความคิดเห็นเกี่ยวกับมาตรฐานเองสามารถส่งไปยังกลุ่มทำงาน CSS และ SVG ผ่านรายชื่ออีเมล public-fx

ข้อมูลอัปเดตเดือนตุลาคม 2014: Chrome 39 รองรับวิธีการเพิ่มเติมหลายวิธีที่เกี่ยวข้องกับการควบคุมการเล่น เช่น play(), pause() และ reverse() นอกจากนี้ยังรองรับการข้ามไปยังจุดที่ต้องการในไทม์ไลน์ของภาพเคลื่อนไหวผ่านพร็อพเพอร์ตี้ currentTime ด้วย คุณสามารถดูฟังก์ชันการทํางานนี้ได้ในเดโมใหม่นี้

ขอขอบคุณ Addy Osmani และ Max Heinritz ที่ให้ความช่วยเหลือเกี่ยวกับโพสต์นี้