การปรับปรุง Web Animations API ใน Chromium 84

การจัดระเบียบภาพเคลื่อนไหวด้วย Promise, การเพิ่มประสิทธิภาพด้วยภาพเคลื่อนไหวที่เปลี่ยนทดแทนได้, ภาพเคลื่อนไหวที่ราบรื่นขึ้นด้วยโหมดคอมโพสิต และอื่นๆ

เผยแพร่: 27 พฤษภาคม 2020

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

Web Animations API เป็นเครื่องมือที่ช่วยให้นักพัฒนาซอฟต์แวร์เขียนภาพเคลื่อนไหวแบบบังคับด้วย JavaScript ได้ มาตรฐานนี้เขียนขึ้นเพื่อรองรับทั้งการใช้งานภาพเคลื่อนไหวและการเปลี่ยน CSS รวมถึงช่วยให้พัฒนาเอฟเฟกต์ในอนาคตได้ ตลอดจนจัดเรียงและกำหนดเวลาเอฟเฟกต์ที่มีอยู่

แม้ว่า Firefox และ Safari จะมีฟีเจอร์ข้อกำหนดครบชุดอยู่แล้ว แต่ Chromium 84 ยังได้นำฟีเจอร์จำนวนมากที่ก่อนหน้านี้ไม่รองรับมาไว้ใน Chrome และ Edge ซึ่งช่วยให้เกิดความสามารถในการทำงานร่วมกันระหว่างเบราว์เซอร์ต่างๆ ได้

Web Animations API มีการใช้งาน Chromium ในเวอร์ชัน 36 ครั้งแรกเมื่อเดือนกรกฎาคม 2014 ตอนนี้ข้อกำหนดจะสมบูรณ์แล้วในเวอร์ชัน 84 ซึ่งจะเปิดตัวในเดือนกรกฎาคม 2020
ประวัติอันยาวนานของ Web Animations API ใน Chromium

เริ่มต้นใช้งาน

การสร้างภาพเคลื่อนไหวโดยใช้ Web Animations API นั้นคุ้นเคยมากหากคุณเคยใช้กฎ @keyframe ก่อนอื่น คุณจะต้องสร้างออบเจ็กต์เฟรมหลัก ลักษณะของโค้ด CSS อาจมีลักษณะเช่นนี้

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

จะมีลักษณะเช่นนี้ใน JavaScript

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

ตำแหน่งที่คุณตั้งค่าพารามิเตอร์สำหรับภาพเคลื่อนไหวใน CSS

.modal {
  animation: openAnimation 1s 1 ease-in;
}

คุณจะตั้งค่าใน JS ดังนี้

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

จำนวนโค้ดก็ใกล้เคียงกัน แต่เมื่อใช้ JavaScript คุณจะได้รับพลังพิเศษ 2-3 อย่างที่คุณไม่มีใน CSS เพียงอย่างเดียว ซึ่งรวมถึงความสามารถในการจัดลำดับเอฟเฟกต์และการควบคุมสถานะการเล่นที่มากขึ้น

เกิน element.animate()

อย่างไรก็ตาม การอัปเดตนี้ทำให้ Web Animations API ไม่จํากัดเฉพาะภาพเคลื่อนไหวที่สร้างโดยใช้ element.animate() อีกต่อไป นอกจากนี้ เรายังจัดการภาพเคลื่อนไหวและการเปลี่ยนภาพ CSS ได้ด้วย

getAnimations() เป็นเมธอดที่แสดงผลภาพเคลื่อนไหวทั้งหมดในองค์ประกอบ ไม่ว่าจะสร้างโดยใช้ element.animate() หรือใช้กฎ CSS (ภาพเคลื่อนไหวหรือการเปลี่ยน CSS) ตัวอย่างลักษณะของการดำเนินการมีดังนี้

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

วิธีเรียบเรียงภาพเคลื่อนไหวแบบมีคำสัญญา

ใน Chromium 84 คุณจะมี 2 วิธีที่ใช้กับ Promise ได้ ได้แก่ animation.ready และ animation.finished

  • animation.ready ช่วยให้คุณรอให้การเปลี่ยนแปลงที่รอดำเนินการมีผล (นั่นคือ การสลับระหว่างวิธีการควบคุมการเล่น เช่น เล่นและหยุดชั่วคราว)
  • animation.finished มีวิธีเรียกใช้โค้ด JavaScript ที่กําหนดเองเมื่อภาพเคลื่อนไหวเสร็จสมบูรณ์

ต่อจากตัวอย่างของเราและสร้างเชนภาพเคลื่อนไหวที่ประสานกันด้วย animation.finished ในตัวอย่างนี้คุณมีการเปลี่ยนรูปแบบแนวตั้ง (scaleY) ตามด้วยการเปลี่ยนรูปแบบแนวนอน (scaleX) ตามด้วยการเปลี่ยนแปลงความทึบแสงในองค์ประกอบย่อย

การใช้การเปลี่ยนรูปแบบและความทึบแสงกับองค์ประกอบโมดัลเปิด ดูตัวอย่างใน Codepen
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

เราได้เชื่อมโยงภาพเคลื่อนไหวเหล่านี้โดยใช้ animation.finished.then() ก่อนที่จะเรียกใช้ชุดภาพเคลื่อนไหวถัดไปในเชน วิธีนี้จะทำให้ภาพเคลื่อนไหวปรากฏตามลำดับ และคุณยังใช้เอฟเฟกต์กับองค์ประกอบเป้าหมายต่างๆ ด้วยการตั้งค่าตัวเลือกที่แตกต่างกันได้ด้วย (เช่น ความเร็วและความนุ่มนวล)

ใน CSS การสร้างภาพเคลื่อนไหวนี้ขึ้นมาใหม่จะยุ่งยากมาก โดยเฉพาะเมื่อใช้ภาพเคลื่อนไหวที่ไม่ซ้ำกันแต่เรียงต่อกันกับองค์ประกอบหลายรายการ คุณต้องใช้ @keyframe จัดเรียงเปอร์เซ็นต์เวลาที่ถูกต้องเพื่อวางภาพเคลื่อนไหว และใช้ animation-delay ก่อนเรียกใช้ภาพเคลื่อนไหวตามลำดับ

ตัวอย่างเช่น เล่น หยุดชั่วคราว และย้อนกลับ

สิ่งที่เปิดได้ควรปิด แต่โชคดีที่ตั้งแต่ Chromium 39 เป็นต้นไป Web Animations API ช่วยให้เราสามารถเล่น หยุดชั่วคราว และเล่นภาพเคลื่อนไหวย้อนกลับได้

คุณสามารถใช้ภาพเคลื่อนไหวที่แสดงก่อนหน้านี้และทำให้ภาพเคลื่อนไหวย้อนกลับอย่างราบรื่นเมื่อคลิกปุ่มอีกครั้งโดยใช้ .reverse() วิธีนี้ช่วยให้คุณสร้างการโต้ตอบที่ราบรื่นและตรงกับบริบทมากขึ้นสําหรับโมดัล

ตัวอย่างการเปิดและปิดโมดัลเมื่อคลิกปุ่ม ดูการสาธิตใน Glitch

สิ่งที่คุณทำได้คือสร้างภาพเคลื่อนไหวที่รอเล่น 2 รายการ (openModal และการเปลี่ยนความทึบในบรรทัด) จากนั้นหยุดภาพเคลื่อนไหวรายการใดรายการหนึ่งชั่วคราวเพื่อรอจนกว่าอีกรายการหนึ่งจะเล่นเสร็จ จากนั้นคุณจะใช้สัญญาได้ว่ารอให้แต่ละรายการเสร็จก่อนแล้วค่อยเล่น สุดท้าย ให้ตรวจสอบว่ามีการตั้งค่า Flag หรือไม่ จากนั้นจึงเล่นภาพเคลื่อนไหวแต่ละรายการย้อนกลับ

ตัวอย่าง: การโต้ตอบแบบไดนามิกกับเฟรมหลักบางส่วน

ตัวอย่างการกำหนดเป้าหมายใหม่เมื่อการคลิกเมาส์ปรับภาพเคลื่อนไหวไปยังตำแหน่งใหม่ ดูการสาธิตใน Glitch
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

ในตัวอย่างนี้ มีเพียงคีย์เฟรมเดียวและไม่มีตำแหน่งเริ่มต้นที่ระบุ นี่เป็นตัวอย่างการใช้คีย์เฟรมบางส่วน แฮนเดิลเมาส์จะทํางาน 2 อย่าง ได้แก่ ตั้งค่าตําแหน่งสิ้นสุดใหม่และเรียกให้ภาพเคลื่อนไหวใหม่แสดง ระบบจะอนุมานตำแหน่งเริ่มต้นใหม่จากตำแหน่งพื้นฐานปัจจุบัน

คุณเรียกใช้ทรานซิชันใหม่ได้ในขณะที่ทรานซิชันที่มีอยู่ยังทำงานอยู่ ซึ่งหมายความว่าการเปลี่ยนปัจจุบันจะหยุดชะงัก และจะมีการสร้างใหม่ขึ้น

การปรับปรุงประสิทธิภาพด้วยภาพเคลื่อนไหวที่เปลี่ยนได้

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

หางดาวจะเคลื่อนไหวเมื่อเมาส์เคลื่อนไหว ดูการสาธิตเกี่ยวกับ Glitch
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

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

  1. ภาพเคลื่อนไหวเสร็จแล้ว
  2. มีภาพเคลื่อนไหวตั้งแต่ 1 ภาพขึ้นไปในลำดับผสมซึ่งทำเสร็จแล้วเช่นกัน
  3. ภาพเคลื่อนไหวใหม่แสดงภาพเคลื่อนไหวของพร็อพเพอร์ตี้เดียวกัน

คุณสามารถดูจํานวนภาพเคลื่อนไหวที่แทนที่ได้โดยนับจํานวนภาพเคลื่อนไหวที่นําออกแต่ละรายการโดยใช้ anim.onremove เพื่อเรียกใช้ตัวนับ

ยังมีวิธีอื่นๆ อีก 2-3 วิธีที่จะช่วยให้คุณควบคุมภาพเคลื่อนไหวได้มากยิ่งขึ้น ดังนี้

  • animation.replaceState() มีไว้เพื่อติดตามว่าภาพเคลื่อนไหวทำงานอยู่ คงอยู่ หรือถูกนำออก
  • animation.commitStyles() จะอัปเดตสไตล์ขององค์ประกอบตามสไตล์พื้นฐานพร้อมกับภาพเคลื่อนไหวทั้งหมดในองค์ประกอบในคำสั่งคอมโพสิท
  • animation.persist() ทําเครื่องหมายภาพเคลื่อนไหวว่าไม่สามารถแทนที่

ภาพเคลื่อนไหวที่ราบรื่นยิ่งขึ้นด้วยโหมดคอมโพสิต

เมื่อใช้ Web Animations API ตอนนี้คุณตั้งค่าโหมดคอมโพสิตของภาพเคลื่อนไหวได้แล้ว ซึ่งหมายความว่าภาพเคลื่อนไหวจะเพิ่มหรือสะสมได้ นอกเหนือจากโหมดเริ่มต้นของ "แทนที่" โหมดผสมช่วยให้นักพัฒนาซอฟต์แวร์เขียนภาพเคลื่อนไหวที่แตกต่างกันและสามารถควบคุมวิธีรวมเอฟเฟกต์ได้ ขณะนี้รองรับโหมดผสม 3 โหมด ได้แก่ 'replace' (โหมดเริ่มต้น), 'add' และ 'accumulate'

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

การสาธิตโหมดคอมโพสิตเริ่มต้น เพิ่ม และสะสม ดูการสาธิตใน Glitch

ในโหมดผสม 'replace' เริ่มต้น ภาพเคลื่อนไหวสุดท้ายจะแทนที่พร็อพเพอร์ตี้ Transform และสิ้นสุดที่ rotate(360deg) scale(1.4) สำหรับ 'add' คอมโพสิตจะเพิ่มการหมุนเวียนและคูณสเกลเพื่อให้ได้สถานะสุดท้ายเป็น rotate(720deg) scale(1.96) 'accumulate' รวมการเปลี่ยนรูปแบบเข้าด้วยกัน ผลลัพธ์ที่ได้คือ rotate(720deg) scale(1.8) ดูข้อมูลเพิ่มเติมเกี่ยวกับความซับซ้อนของโหมดคอมโพสิทเหล่านี้ได้ที่การแจกแจง CompositeOperation และ CompositeOperationOrAuto จากข้อกำหนดของ Web Animations

ดูตัวอย่างองค์ประกอบ UI ต่อไปนี้

เมนูแบบเลื่อนลงที่เด้งขึ้นและมีภาพเคลื่อนไหวแบบคอมโพสิต 2 รายการ ดูการสาธิตใน Glitch

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

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

การพัฒนา Web Animations API ในอนาคต

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