ทำให้องค์ประกอบเคลื่อนไหวขณะเลื่อนด้วยภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน

ดูวิธีใช้งานไทม์ไลน์แบบเลื่อนและดูไทม์ไลน์เพื่อสร้างภาพเคลื่อนไหวแบบเลื่อนที่ขับเคลื่อนด้วยการประกาศ

ภาพเคลื่อนไหวที่ทำงานตามการเลื่อน

การรองรับเบราว์เซอร์

  • Chrome: 115
  • Edge: 115
  • Firefox: อยู่หลังธง
  • Safari: ไม่รองรับ

แหล่งที่มา

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

ตัวบ่งชี้การอ่านที่ด้านบนของเอกสาร ซึ่งขับเคลื่อนโดยการเลื่อน

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

รูปภาพในหน้านี้จะค่อยๆ ปรากฏขึ้นเมื่อเข้ามาอยู่ในมุมมอง

วิธีคลาสสิกในการสร้างเอฟเฟกต์ประเภทนี้คือตอบสนองต่อเหตุการณ์การเลื่อนในเธรดหลัก ซึ่งจะทำให้เกิดปัญหาหลัก 2 ข้อดังนี้

  • เบราว์เซอร์สมัยใหม่จะเลื่อนในกระบวนการแยกต่างหาก จึงส่งเหตุการณ์การเลื่อนแบบไม่พร้อมกัน
  • ภาพเคลื่อนไหวในเธรดหลักอาจกระตุก

ซึ่งทำให้การสร้างภาพเคลื่อนไหวที่ทำงานด้วยการปัดที่มีประสิทธิภาพและซิงค์กับการปัดเป็นไปไม่ได้หรือทำได้ยากมาก

ตั้งแต่ Chrome เวอร์ชัน 115 เป็นต้นไป จะมีชุด API และแนวคิดใหม่ที่คุณสามารถใช้เพื่อเปิดใช้ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนแบบประกาศได้ ซึ่งได้แก่ Scroll Timelines และ View Timelines

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

ภาพเคลื่อนไหวบนเว็บ โดยสรุป

ภาพเคลื่อนไหวบนเว็บด้วย CSS

หากต้องการสร้างภาพเคลื่อนไหวใน CSS ให้กําหนดชุดคีย์เฟรมโดยใช้@keyframes at-rule ลิงก์กับองค์ประกอบโดยใช้พร็อพเพอร์ตี้ animation-name พร้อมกับตั้งค่า animation-duration เพื่อกำหนดระยะเวลาของภาพเคลื่อนไหว ยังมีanimation-*พร็อพเพอร์ตี้แบบเต็มanimation-easing-functionและ animation-fill-mode อีกมากมายที่รวมไว้ในanimationแบบย่อได้

ตัวอย่างเช่น ภาพเคลื่อนไหวที่ขยายองค์ประกอบในแกน X ไปพร้อมกับเปลี่ยนสีพื้นหลัง

@keyframes scale-up {
  from {
    background-color: red;
    transform: scaleX(0);
  }
  to {
    background-color: darkred;
    transform: scaleX(1);
  }
}

#progressbar {
  animation: 2.5s linear forwards scale-up;
}

ภาพเคลื่อนไหวบนเว็บด้วย JavaScript

ใน JavaScript คุณสามารถใช้ Web Animations API เพื่อให้ได้ผลลัพธ์แบบเดียวกัน ซึ่งทำได้โดยการสร้างอินสแตนซ์ Animation และ KeyFrameEffect ใหม่ หรือใช้เมธอด Element animate() ที่สั้นกว่ามาก

document.querySelector('#progressbar').animate(
  {
    backgroundColor: ['red', 'darkred'],
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    duration: 2500,
    fill: 'forwards',
    easing: 'linear',
   }
);

ผลลัพธ์ที่แสดงผลของข้อมูลโค้ด JavaScript ด้านบนนี้เหมือนกับ CSS เวอร์ชันก่อนหน้า

ไทม์ไลน์ภาพเคลื่อนไหว

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

ข้อกำหนดเกี่ยวกับภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนกำหนดไทม์ไลน์ใหม่ 2 ประเภทที่คุณสามารถใช้ได้ ดังนี้

  • ไทม์ไลน์ความคืบหน้าในการเลื่อน: ไทม์ไลน์ที่ลิงก์กับตำแหน่งการเลื่อนของคอนเทนเนอร์การเลื่อนตามแกนใดแกนหนึ่ง
  • ดูไทม์ไลน์ความคืบหน้า: ไทม์ไลน์ที่ลิงก์กับตําแหน่งสัมพัทธ์ขององค์ประกอบหนึ่งๆ ภายในคอนเทนเนอร์การเลื่อน

ไทม์ไลน์ความคืบหน้าของการเลื่อน

ไทม์ไลน์ความคืบหน้าในการเลื่อนคือไทม์ไลน์ภาพเคลื่อนไหวที่เชื่อมโยงกับความคืบหน้าในตำแหน่งการเลื่อนของคอนเทนเนอร์การเลื่อน ซึ่งเรียกอีกอย่างว่า scrollport หรือ scroller ตามแนวแกนใดแกนหนึ่ง ซึ่งจะแปลงตำแหน่งในช่วงการเลื่อนเป็นเปอร์เซ็นต์ของความคืบหน้า

ตำแหน่งการเลื่อนเริ่มต้นแสดงถึงความคืบหน้า 0% และตำแหน่งการเลื่อนสิ้นสุดแสดงถึงความคืบหน้า 100% ในการแสดงภาพต่อไปนี้ คุณจะเห็นความคืบหน้านับจาก 0% ถึง 100% เมื่อเลื่อนแถบเลื่อนจากบนลงล่าง

การแสดงข้อมูลผ่านภาพไทม์ไลน์ความคืบหน้าของการเลื่อน เมื่อคุณเลื่อนไปที่ด้านล่างของแถบเลื่อน ค่าความคืบหน้าจะนับจาก 0% เป็น 100%

✨ ลองใช้ด้วยตัวคุณเอง

ไทม์ไลน์ความคืบหน้าในการเลื่อนมักจะเรียกสั้นๆ ว่า "ไทม์ไลน์การเลื่อน"

ดูไทม์ไลน์ความคืบหน้า

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

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

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

การแสดงข้อมูลผ่านภาพไทม์ไลน์ความคืบหน้าของมุมมอง ระบบจะนับความคืบหน้าตั้งแต่ 0% ถึง 100% เนื่องจากวัตถุ (กล่องสีเขียว) วิ่งทับตัวเลื่อน

✨ ลองใช้ด้วยตัวคุณเอง

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

ใช้ประโยชน์จากไทม์ไลน์ความคืบหน้าในการเลื่อน

การสร้างไทม์ไลน์ความคืบหน้าในการเลื่อนที่ไม่ระบุตัวตนใน CSS

วิธีที่ง่ายที่สุดในการสร้างไทม์ไลน์การเลื่อนใน CSS คือการใช้ฟังก์ชัน scroll() ซึ่งจะสร้างไทม์ไลน์การเลื่อนแบบไม่ระบุตัวตนที่คุณตั้งเป็นค่าสําหรับพร็อพเพอร์ตี้ animation-timeline ใหม่ได้

ตัวอย่าง

@keyframes animate-it {  }

.subject {
  animation: animate-it linear;
  animation-timeline: scroll(root block);
}

ฟังก์ชัน scroll() ยอมรับอาร์กิวเมนต์ <scroller> และ <axis>

ค่าที่ยอมรับสำหรับอาร์กิวเมนต์ <scroller> มีดังนี้

  • nearest: ใช้คอนเทนเนอร์การเลื่อนของบรรพบุรุษที่อยู่ใกล้ที่สุด (ค่าเริ่มต้น)
  • root: ใช้วิวพอร์ตเอกสารเป็นคอนเทนเนอร์การเลื่อน
  • self: ใช้องค์ประกอบนั้นๆ เป็นที่เก็บแบบเลื่อน

ค่าที่ยอมรับสำหรับอาร์กิวเมนต์ <axis> มีดังนี้

  • block: ใช้การวัดความคืบหน้าตามแกนบล็อกของคอนเทนเนอร์แบบเลื่อน (ค่าเริ่มต้น)
  • inline: ใช้การวัดความคืบหน้าตามแกนแนวนอนของคอนเทนเนอร์การเลื่อน
  • y: ใช้การวัดความคืบหน้าตามแกน Y ของคอนเทนเนอร์การเลื่อน
  • x: ใช้การวัดความคืบหน้าตามแกน x ของคอนเทนเนอร์แบบเลื่อน

ตัวอย่างเช่น ในการเชื่อมโยงภาพเคลื่อนไหวกับตัวเลื่อนรูทบนแกนบล็อก ค่าที่ส่งผ่านไปยัง scroll() คือ root และ block เมื่อรวมกันแล้ว ค่าที่ได้คือ scroll(root block)

การสาธิต: สัญญาณบอกสถานะความคืบหน้าในการอ่าน

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

การสาธิต: สัญญาณบอกสถานะความคืบหน้าในการอ่าน

✨ ลองใช้ด้วยตัวคุณเอง

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

<body>
  <div id="progress"></div>
  …
</body>
@keyframes grow-progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

#progress {
  position: fixed;
  left: 0; top: 0;
  width: 100%; height: 1em;
  background: red;

  transform-origin: 0 50%;
  animation: grow-progress auto linear;
  animation-timeline: scroll();
}

ไทม์ไลน์สำหรับภาพเคลื่อนไหว grow-progress ในองค์ประกอบ #progress ได้รับการตั้งค่าเป็นไทม์ไลน์ที่ไม่ระบุตัวตนซึ่งสร้างขึ้นโดยใช้ scroll() ไม่ได้ให้อาร์กิวเมนต์กับ scroll() ไว้ ระบบจึงจะกลับไปใช้ค่าเริ่มต้น

แถบเลื่อนเริ่มต้นที่จะติดตามคือ nearest และแกนเริ่มต้นคือ block วิธีนี้กำหนดเป้าหมายไปยัง Scroller รูทได้อย่างมีประสิทธิภาพ เนื่องจากเป็น Scroller ที่ใกล้ที่สุดขององค์ประกอบ #progress ในขณะเดียวกันก็ติดตามทิศทางของบล็อก

การสร้างไทม์ไลน์ความคืบหน้าในการเลื่อนที่มีชื่อใน CSS

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

หากต้องการสร้างไทม์ไลน์ความคืบหน้าในการเลื่อนที่มีชื่อบนองค์ประกอบ ให้ตั้งค่าพร็อพเพอร์ตี้ scroll-timeline-name CSS ในคอนเทนเนอร์การเลื่อนเป็นตัวระบุที่ต้องการ ค่าต้องขึ้นต้นด้วย --

หากต้องการปรับแต่งแกนที่จะติดตาม ให้ประกาศพร็อพเพอร์ตี้ scroll-timeline-axis ด้วย ค่าที่อนุญาตจะเหมือนกับอาร์กิวเมนต์ <axis> ของ scroll()

สุดท้าย หากต้องการลิงก์ภาพเคลื่อนไหวกับไทม์ไลน์ความคืบหน้าของการเลื่อน ให้ตั้งค่าพร็อพเพอร์ตี้ animation-timeline ในองค์ประกอบที่ต้องแสดงภาพเคลื่อนไหวเป็นค่าเดียวกับตัวระบุที่ใช้สำหรับ scroll-timeline-name

ตัวอย่างโค้ด

@keyframes animate-it {  }

.scroller {
  scroll-timeline-name: --my-scroller;
  scroll-timeline-axis: inline;
}

.scroller .subject {
  animation: animate-it linear;
  animation-timeline: --my-scroller;
}

คุณรวม scroll-timeline-name และ scroll-timeline-axis ไว้ในตัวย่อ scroll-timeline ได้หากต้องการ เช่น

scroll-timeline: --my-scroller inline;

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

สาธิต: ตัวบ่งชี้ขั้นตอนของภาพสไลด์แนวนอน

✨ ลองใช้ด้วยตัวคุณเอง

มาร์กอัปพื้นฐานสำหรับแกลเลอรีมีดังนี้

<div class="gallery" style="--num-images: 2;">
  <div class="gallery__scrollcontainer">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">…</div>
    <div class="gallery__entry">…</div>
  </div>
</div>

องค์ประกอบ .gallery__progress อยู่ในตําแหน่งแบบสัมบูรณ์ภายในองค์ประกอบ .gallery ขนาดเริ่มต้นจะกำหนดโดยพร็อพเพอร์ตี้ที่กำหนดเอง --num-images

.gallery {
  position: relative;
}


.gallery__progress {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 1em;
  transform: scaleX(calc(1 / var(--num-images)));
}

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

@keyframes grow-progress {
  to { transform: scaleX(1); }
}

.gallery__scrollcontainer {
  overflow-x: scroll;
  scroll-timeline: --gallery__scrollcontainer inline;
}
.gallery__progress {
  animation: auto grow-progress linear forwards;
  animation-timeline: --gallery__scrollcontainer;
}

การสร้างไทม์ไลน์ความคืบหน้าในการเลื่อนด้วย JavaScript

หากต้องการสร้างไทม์ไลน์การเลื่อนใน JavaScript ให้สร้างอินสแตนซ์ใหม่ของคลาส ScrollTimeline ส่งกระเป๋าพร็อพเพอร์ตี้ที่มี source และ axis ที่ต้องการติดตาม

  • source: การอ้างอิงองค์ประกอบที่มีตัวเลื่อนที่คุณต้องการติดตาม ใช้ document.documentElement เพื่อกําหนดเป้าหมายไปยังตัวเลื่อนระดับรูท
  • axis: กำหนดแกนที่จะติดตาม ค่าที่ยอมรับคือ block, inline, x และ y ซึ่งคล้ายกับตัวแปร CSS
const tl = new ScrollTimeline({
  source: document.documentElement,
});

หากต้องการแนบกับภาพเคลื่อนไหวบนเว็บ ให้ส่งเป็นพร็อพเพอร์ตี้ timeline และละเว้น duration หากมี

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
});

สาธิต: สัญญาณบอกสถานะความคืบหน้าในการอ่าน (เวอร์ชันปรับปรุง)

หากต้องการสร้างตัวบ่งชี้ความคืบหน้าในการอ่านด้วย JavaScript อีกครั้งขณะใช้มาร์กอัปเดียวกัน ให้ใช้โค้ด JavaScript ต่อไปนี้

const $progressbar = document.querySelector('#progress');

$progressbar.style.transformOrigin = '0% 50%';
$progressbar.animate(
  {
    transform: ['scaleX(0)', 'scaleX(1)'],
  },
  {
    fill: 'forwards',
    timeline: new ScrollTimeline({
      source: document.documentElement,
    }),
  }
);

ผลลัพธ์ที่มองเห็นจะเหมือนกันในเวอร์ชัน CSS โดย timeline ที่สร้างขึ้นจะติดตามตัวเลื่อนรูทและปรับขนาด #progress ในแกน x จาก 0% เป็น 100% ขณะที่คุณเลื่อนหน้าเว็บ

✨ ลองใช้ด้วยตัวคุณเอง

ใช้ประโยชน์จากไทม์ไลน์ความคืบหน้าของมุมมอง

การสร้างไทม์ไลน์ความคืบหน้าของมุมมองแบบไม่ระบุตัวตนใน CSS

หากต้องการสร้างไทม์ไลน์ความคืบหน้าของมุมมอง ให้ใช้ฟังก์ชัน view() อาร์กิวเมนต์ที่ยอมรับคือ <axis> และ <view-timeline-inset>

  • <axis> จะเหมือนกับในไทม์ไลน์ความคืบหน้าของการเลื่อนและเป็นตัวกำหนดว่าจะติดตามแกนใด ค่าเริ่มต้นคือ block
  • เมื่อใช้ <view-timeline-inset> คุณจะระบุออฟเซ็ต (บวกหรือค่าลบ) เพื่อปรับขอบเขตเมื่อระบบพิจารณาว่าองค์ประกอบอยู่ในมุมมองหรือไม่ ค่าต้องเป็นเปอร์เซ็นต์หรือ auto โดย auto เป็นค่าเริ่มต้น

เช่น หากต้องการเชื่อมโยงภาพเคลื่อนไหวกับองค์ประกอบที่ตัดกับตัวเลื่อนบนแกนบล็อก ให้ใช้ view(block) ตั้งค่านี้เป็นค่าสําหรับพร็อพเพอร์ตี้ animation-timeline เช่นเดียวกับ scroll() และอย่าลืมตั้งค่า animation-duration เป็น auto

เมื่อใช้รหัสต่อไปนี้ img ทุกรายการจะค่อยๆ จางลงเมื่อข้ามวิวพอร์ตในขณะที่คุณเลื่อน

@keyframes reveal {
  from { opacity: 0; }
  to { opacity: 1; }
}

img {
  animation: reveal linear;
  animation-timeline: view();
}

ช่วงพัก: ดูช่วงไทม์ไลน์

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

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

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

ช่วงไทม์ไลน์ของมุมมองที่เป็นไปได้ซึ่งคุณกำหนดเป้าหมายได้มีดังนี้

  • cover: แสดงไทม์ไลน์ความคืบหน้าการดูทั้งหมด
  • entry: แสดงช่วงที่กล่องหลักเข้าสู่ช่วงการมองเห็นความคืบหน้าของมุมมอง
  • exit: แสดงช่วงที่กล่องหลักออกจากช่วงการมองเห็นความคืบหน้าของมุมมอง
  • entry-crossing: แสดงช่วงที่ช่องหลักพาดผ่านขอบสิ้นสุด
  • exit-crossing: แสดงช่วงระหว่างที่กล่องหลักตัดผ่านขอบเส้นขอบเริ่มต้น
  • contain: แสดงช่วงที่กล่องหลักอยู่ภายในหรือครอบคลุมช่วงการมองเห็นความคืบหน้าในการดูภายในวิวพอร์ตอย่างเต็มรูปแบบ ซึ่งขึ้นอยู่กับว่าวัตถุสูงกว่าหรือต่ำกว่าตัวเลื่อน

หากต้องการกําหนดช่วง คุณต้องตั้งค่า range-start และ range-end โดยแต่ละรายการประกอบด้วย range-name (ดูรายการด้านบน) และ range-offset เพื่อระบุตําแหน่งใน range-name นั้น โดยปกติแล้ว ช่วงการเลื่อนจะระบุเป็นเปอร์เซ็นต์ในช่วง 0% ถึง 100% แต่คุณระบุความยาวคงที่ เช่น 20em ก็ได้

เช่น หากต้องการเรียกใช้ภาพเคลื่อนไหวจากตอนที่วัตถุเข้าใกล้ ให้เลือก entry 0% เป็นช่วงเริ่มต้น หากต้องการให้เสร็จสิ้นภายในเวลาที่ผู้สมัครเข้ามา ให้เลือก entry 100% เป็นค่าของ range-end

ใน CSS คุณจะตั้งค่านี้โดยใช้พร็อพเพอร์ตี้ animation-range ตัวอย่าง

animation-range: entry 0% entry 100%;

ใน JavaScript ให้ใช้พร็อพเพอร์ตี้ rangeStart และ rangeEnd

$el.animate(
  keyframes,
  {
    timeline: tl,
    rangeStart: 'entry 0%',
    rangeEnd: 'entry 100%',
  }
);

ใช้เครื่องมือที่ฝังอยู่ด้านล่างเพื่อดูว่าชื่อช่วงแต่ละรายการหมายถึงอะไร และเปอร์เซ็นต์ส่งผลต่อตําแหน่งเริ่มต้นและสิ้นสุดอย่างไร ลองตั้งค่า range-start เป็น entry 0% และ range-end เป็น cover 50% แล้วลากแถบเลื่อนเพื่อดูผลลัพธ์ของภาพเคลื่อนไหว

เครื่องมือแสดงภาพช่วงไทม์ไลน์ของมุมมอง ซึ่งดูได้ที่ https://goo.gle/view-timeline-range-tool

ดูไฟล์บันทึก

คุณอาจสังเกตเห็นขณะใช้เครื่องมือช่วงไทม์ไลน์ของมุมมองนี้ว่าช่วงบางช่วงสามารถกําหนดเป้าหมายได้โดยใช้ชุดค่าผสมของชื่อช่วง + การเลื่อนช่วง 2 ชุดที่แตกต่างกัน เช่น entry 0%, entry-crossing 0% และ cover 0% ทั้งหมดกำหนดเป้าหมายเป็นพื้นที่เดียวกัน

เมื่อ range-start และ range-end กำหนดเป้าหมายไปยัง range-name เดียวกันและครอบคลุมทั้งช่วงตั้งแต่ 0% ถึง 100% คุณสามารถย่อค่าให้เหลือเพียงชื่อช่วงได้ เช่น animation-range: entry 0% entry 100%; สามารถเขียนใหม่เป็น animation-range: entry ที่สั้นกว่าได้

การสาธิต: การเปิดเผยรูปภาพ

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

การสาธิต: การแสดงภาพ

✨ ลองใช้ด้วยตัวคุณเอง

เอฟเฟกต์การขยายจะสร้างขึ้นโดยใช้ clip-path ที่มีภาพเคลื่อนไหว CSS ที่ใช้สำหรับเอฟเฟกต์นี้คือ

@keyframes reveal {
  from { opacity: 0; clip-path: inset(0% 60% 0% 50%); }
  to { opacity: 1; clip-path: inset(0% 0% 0% 0%); }
}

.revealing-image {
  animation: auto linear reveal both;
  animation-timeline: view();
  animation-range: entry 25% cover 50%;
}

การสร้างไทม์ไลน์ความคืบหน้าที่มีชื่อใน CSS

คุณยังสร้าง "ดูไทม์ไลน์" ที่มีชื่อได้เช่นเดียวกับชื่อ "ไทม์ไลน์ของการเลื่อน" แทนที่จะใช้พร็อพเพอร์ตี้ scroll-timeline-* คุณจะใช้ตัวแปรที่มีคำนำหน้า view-timeline- ซึ่งได้แก่ view-timeline-name และ view-timeline-axis

ค่าประเภทเดียวกันจะมีผล และกฎเดียวกันสำหรับการค้นหาไทม์ไลน์ที่มีชื่อจะมีผล

ตัวอย่าง: การเปิดเผยรูปภาพ (เวอร์ชันปรับปรุง)

การซ่อมแซมเดโมที่เปิดเผยรูปภาพจากก่อนหน้านี้ โค้ดที่แก้ไขแล้วจะมีลักษณะดังนี้

.revealing-image {
  view-timeline-name: --revealing-image;
  view-timeline-axis: block;

  animation: auto linear reveal both;
  animation-timeline: --revealing-image;
  animation-range: entry 25% cover 50%;
}

เมื่อใช้ view-timeline-name: revealing-image ระบบจะติดตามองค์ประกอบภายในแถบเลื่อนที่อยู่ใกล้ที่สุด จากนั้นระบบจะใช้ค่าเดียวกันเป็นค่าสําหรับพร็อพเพอร์ตี้ animation-timeline เอาต์พุตภาพจะเหมือนกับก่อนหน้านี้ทุกประการ

✨ ลองใช้ด้วยตัวคุณเอง

การสร้างไทม์ไลน์ความคืบหน้าการดูใน JavaScript

หากต้องการสร้างไทม์ไลน์มุมมองใน JavaScript ให้สร้างอินสแตนซ์ใหม่ของคลาส ViewTimeline ส่งกระเป๋าพร็อพเพอร์ตี้ที่มี subject ที่ต้องการติดตาม, axis และ inset

  • subject: การอ้างอิงไปยังองค์ประกอบที่คุณต้องการติดตามภายในแถบเลื่อนขององค์ประกอบนั้น
  • axis: แกนที่จะติดตาม ค่าที่ยอมรับคือ block, inline, x และ y ซึ่งคล้ายกับตัวแปร CSS
  • inset: การปรับแถบเลื่อน(บวก) หรือ(ลบ) ของแถบเลื่อนเมื่อพิจารณาว่ากล่องอยู่ในมุมมองหรือไม่
const tl = new ViewTimeline({
  subject: document.getElementById('subject'),
});

หากต้องการแนบกับภาพเคลื่อนไหวบนเว็บ ให้ส่งเป็นพร็อพเพอร์ตี้ timeline และละเว้น duration หากมี (ไม่บังคับ) ส่งข้อมูลช่วงโดยใช้พร็อพเพอร์ตี้ rangeStart และ rangeEnd

$el.animate({
  opacity: [0, 1],
}, {
  timeline: tl,
  rangeStart: 'entry 25%',
  rangeEnd: 'cover 50%',
});

✨ ลองใช้ด้วยตัวคุณเอง

สิ่งอื่นๆ ที่น่าลอง

การแนบกับช่วงไทม์ไลน์ของมุมมองหลายช่วงด้วยคีย์เฟรมชุดเดียว

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

สาธิต: รายชื่อติดต่อ

✨ ลองด้วยตัวเอง

ในการสาธิตนี้ แต่ละองค์ประกอบได้รับการตกแต่งด้วยไทม์ไลน์มุมมอง 1 รายการซึ่งติดตามองค์ประกอบขณะที่ข้ามวิวพอร์ต แต่มีภาพเคลื่อนไหวที่ทำงานตามการเลื่อน 2 รายการแนบอยู่ ภาพเคลื่อนไหว animate-in จะแนบอยู่กับช่วง entry ของไทม์ไลน์ และภาพเคลื่อนไหว animate-out จะแนบอยู่กับช่วง exit ของไทม์ไลน์

@keyframes animate-in {
  0% { opacity: 0; transform: translateY(100%); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes animate-out {
  0% { opacity: 1; transform: translateY(0); }
  100% { opacity: 0; transform: translateY(-100%); }
}

#list-view li {
  animation: animate-in linear forwards,
             animate-out linear forwards;
  animation-timeline: view();
  animation-range: entry, exit;
}

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

@keyframes animate-in-and-out {
  entry 0%  {
    opacity: 0; transform: translateY(100%);
  }
  entry 100%  {
    opacity: 1; transform: translateY(0);
  }
  exit 0% {
    opacity: 1; transform: translateY(0);
  }
  exit 100% {
    opacity: 0; transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

เนื่องจากคีย์เฟรมมีข้อมูลช่วง คุณจึงไม่จำเป็นต้องระบุ animation-range ผลลัพธ์ที่ได้จะเหมือนกับก่อนหน้านี้ทุกประการ

✨ ลองใช้ด้วยตัวคุณเอง

การแนบกับไทม์ไลน์การเลื่อนที่ไม่ใช่ระดับบน

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

คุณต้องนำพร็อพเพอร์ตี้ timeline-scope มาใช้จึงจะดำเนินการนี้ได้ คุณใช้พร็อพเพอร์ตี้นี้เพื่อประกาศไทม์ไลน์ที่มีชื่อนั้นโดยไม่ต้องสร้างจริง ซึ่งจะทำให้ไทม์ไลน์ที่มีชื่อดังกล่าวมีขอบเขตที่กว้างขึ้น ในทางปฏิบัติ คุณจะใช้พร็อพเพอร์ตี้ timeline-scope ในองค์ประกอบหลักที่แชร์เพื่อให้ไทม์ไลน์ของแถบเลื่อนย่อยแนบกับองค์ประกอบหลักได้

เช่น

.parent {
  timeline-scope: --tl;
}
.parent .scroller {
  scroll-timeline: --tl;
}
.parent .scroller ~ .subject {
  animation: animate linear;
  animation-timeline: --tl;
}

ในข้อมูลโค้ดนี้

  • องค์ประกอบ .parent ประกาศไทม์ไลน์ที่มีชื่อ --tl องค์ประกอบย่อยขององค์ประกอบดังกล่าวจะค้นหาและใช้ค่าดังกล่าวเป็นค่าของพร็อพเพอร์ตี้ animation-timeline ได้
  • องค์ประกอบ .scroller กำหนดไทม์ไลน์การเลื่อนโดยใช้ชื่อ --tl โดยค่าเริ่มต้น รายการนี้จะปรากฏแก่ผู้เผยแพร่โฆษณาย่อยเท่านั้น แต่เนื่องจาก .parent ได้ตั้งค่าเป็น scroll-timeline-root จึงเชื่อมโยงด้วย
  • องค์ประกอบ .subject ใช้ไทม์ไลน์ --tl มันเดินขึ้นต้นบรรพบุรุษและพบ --tl บน .parent เมื่อ --tl ใน .parent ชี้ไปที่ --tl ของ .scroller .subject จะติดตามไทม์ไลน์ความคืบหน้าในการเลื่อนของ .scroller

กล่าวคือ คุณสามารถใช้ timeline-root เพื่อย้ายไทม์ไลน์ไปยังบรรพบุรุษ (หรือที่เรียกว่าการยกระดับ) เพื่อให้บรรพบุรุษและรายการย่อยทั้งหมดเข้าถึงไทม์ไลน์นั้นได้

พร็อพเพอร์ตี้ timeline-scope ใช้ได้ทั้งกับไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมอง

การสาธิตและแหล่งข้อมูลเพิ่มเติม

การสาธิตทั้งหมดที่กล่าวถึงในบทความนี้ที่ the Scroll-animations.style mini-site เว็บไซต์ดังกล่าวมีการสาธิตอีกมากมายเพื่อเน้นสิ่งที่เป็นไปได้ด้วยภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน

การสาธิตเพิ่มเติมอีกอย่างหนึ่งคือรายการปกอัลบั้มนี้ ภาพปกแต่ละภาพจะหมุนเป็น 3 มิติขณะอยู่ในจุดสนใจตรงกลาง

สาธิต: Cover Flow

✨ ลองใช้ด้วยตัวคุณเอง

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

สาธิต: การซ้อนการ์ด

✨ ลองด้วยตัวเอง

นอกจากนี้ scroll-driven-animations.style ยังมีคอลเล็กชันเครื่องมือ เช่น ภาพแสดงผลความคืบหน้าของช่วงไทม์ไลน์ของมุมมองที่รวมอยู่ในโพสต์นี้ก่อนหน้านี้

ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนยังอยู่ในหัวข้อมีอะไรใหม่ในภาพเคลื่อนไหวบนเว็บที่ Google I/O ’23 ด้วย