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

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

ภาพเคลื่อนไหวที่ใช้การเลื่อน

การสนับสนุนเบราว์เซอร์

  • 115
  • 115
  • x

แหล่งที่มา

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

สัญญาณบอกสถานะการอ่านที่ด้านบนของเอกสาร ซึ่งขับเคลื่อนด้วยการเลื่อน

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

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

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

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

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

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

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

ภาพเคลื่อนไหวในเว็บ สรุปสั้นๆ

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

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

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

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

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

หากต้องการปรับเปลี่ยนแกนที่จะติดตาม ให้ประกาศพร็อพเพอร์ตี้ 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% เพื่อแสดงว่าคุณกำลังดูรูปภาพที่ 1 จาก 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 อยู่ในตำแหน่งที่แน่นอนภายในองค์ประกอบ Wrapper .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) เช่นเดียวกับ scroll() ให้ตั้งค่านี้เป็นค่าสำหรับพร็อพเพอร์ตี้ animation-timeline และอย่าลืมตั้งค่า animation-duration เป็น auto

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

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

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

Intermezzo: ดูช่วงไทม์ไลน์

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

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

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

ช่วงไทม์ไลน์การดูที่คุณกําหนดเป้าหมายได้มีดังนี้

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

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

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

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

animation-range: entry 0% entry 100%;

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

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

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

วิดีโอ Visualizer สำหรับดูช่วงไทม์ไลน์พร้อมให้ใช้งานที่ https://goo.gle/view-timeline-range-tool

ดูเทปบันทึกภาพ

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

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

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

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

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

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

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

เช่นเดียวกับที่ไทม์ไลน์การเลื่อนตั้งชื่อเวอร์ชันได้ คุณสามารถสร้างชื่อ "ดูไทม์ไลน์" ได้ด้วย คุณใช้ตัวแปรที่นำหน้า view-timeline- ได้แทนพร็อพเพอร์ตี้ scroll-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 ชุด

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

การสาธิต: ข้อมูลรายชื่อติดต่อ

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

ในการสาธิตนี้ องค์ประกอบแต่ละรายการจะตกแต่งด้วยไทม์ไลน์การดู 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 ช่วง คุณก็สร้างคีย์เฟรม 1 ชุดที่มีข้อมูลของช่วงอยู่แล้วได้

@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 กับทั้งไทม์ไลน์ในการเลื่อนและไทม์ไลน์การดู

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

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

หนึ่งในเดโมเพิ่มเติมคือรายการปกอัลบั้มนี้ หน้าปกแต่ละฉบับจะหมุนในแบบ 3 มิติโดยใช้สปอตไลท์ตรงกลาง

การสาธิต: ขั้นตอนการร้องเพลงคัฟเวอร์

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

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

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

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

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

นอกจากนี้ ยังมีเนื้อหาอื่นๆ ที่ขับเคลื่อนด้วยการเลื่อนได้ในมีอะไรใหม่ใน Web Animations ที่งาน Google I/O ปี 2023