ดูวิธีใช้ไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมองเพื่อสร้างภาพเคลื่อนไหวที่ทำงานตามการเลื่อนในลักษณะที่ประกาศ
เผยแพร่: 5 พฤษภาคม 2023
ภาพเคลื่อนไหวที่ทำงานตามการเลื่อน
ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนเป็นรูปแบบ 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% เมื่อเลื่อนแถบเลื่อนจากบนลงล่าง
✨ ลองใช้ด้วยตัวคุณเอง
ไทม์ไลน์ความคืบหน้าในการเลื่อนมักจะเรียกสั้นๆ ว่า "ไทม์ไลน์การเลื่อน"
ดูไทม์ไลน์ความคืบหน้า
ไทม์ไลน์ประเภทนี้เชื่อมโยงกับความคืบหน้าแบบสัมพัทธ์ขององค์ประกอบหนึ่งๆ ภายในคอนเทนเนอร์การเลื่อน ระบบจะติดตามออฟเซตการเลื่อนของเครื่องมือเลื่อนเช่นเดียวกับไทม์ไลน์ความคืบหน้าของการเลื่อน ซึ่งต่างจากไทม์ไลน์ความคืบหน้าในการเลื่อนตรงที่ตำแหน่งสัมพัทธ์ของวัตถุภายในแถบเลื่อนจะเป็นตัวกำหนดความคืบหน้า
ซึ่งคล้ายกับวิธีการทำงานของ IntersectionObserver ที่ติดตามระดับการมองเห็นองค์ประกอบในแถบเลื่อน หากไม่เห็นองค์ประกอบในแถบเลื่อน แสดงว่าองค์ประกอบไม่ได้ตัดกัน หากมองเห็นส่วนใดส่วนหนึ่งขององค์ประกอบภายในแถบเลื่อน แสดงว่าองค์ประกอบนั้นตัดกัน
ไทม์ไลน์ความคืบหน้าของการดูจะเริ่มต้นจากตอนที่วัตถุเริ่มตัดกับแถบเลื่อนและสิ้นสุดเมื่อวัตถุหยุดตัดกับแถบเลื่อน ในภาพแสดงข้อมูลต่อไปนี้ คุณจะเห็นความคืบหน้าเริ่มนับจาก 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% เพื่อระบุว่าคุณกําลังดูรูปภาพ 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 อยู่ในตําแหน่งแบบสัมบูรณ์ภายในองค์ประกอบ .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% แล้วลากแถบเลื่อนเพื่อดูผลลัพธ์ของภาพเคลื่อนไหว
ดูไฟล์บันทึก
คุณอาจสังเกตเห็นขณะใช้เครื่องมือช่วงไทม์ไลน์ของมุมมองนี้ว่าช่วงบางช่วงสามารถกําหนดเป้าหมายได้โดยใช้ชุดค่าผสมของชื่อช่วง + การเลื่อนช่วง 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
คุณสามารถสร้างไทม์ไลน์มุมมองที่มีชื่อได้เช่นเดียวกับไทม์ไลน์การเลื่อนที่มีชื่อ คุณใช้ตัวแปรที่มีคำนำหน้า 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 ระบบจะติดตามองค์ประกอบภายใน Scroller ที่ใกล้ที่สุด จากนั้นระบบจะใช้ค่าเดียวกันเป็นค่าสําหรับพร็อพเพอร์ตี้ 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เท่านั้นที่จะมองเห็นได้ แต่เนื่องจาก.parentตั้งค่าเป็นscroll-timeline-root.parentจึงแนบอยู่กับscroll-timeline-root
- องค์ประกอบ .subjectใช้ไทม์ไลน์--tlรายการดังกล่าวจะเดินขึ้นลําดับชั้นของบรรพบุรุษและพบ--tlใน.parentเมื่อ--tlใน.parentชี้ไปที่--tlของ.scroller.subjectจะติดตามไทม์ไลน์ความคืบหน้าในการเลื่อนของ.scroller
กล่าวคือ คุณสามารถใช้ timeline-root เพื่อย้ายไทม์ไลน์ไปยังบรรพบุรุษ (หรือที่เรียกว่าการยกระดับ) เพื่อให้บรรพบุรุษและรายการย่อยทั้งหมดเข้าถึงไทม์ไลน์นั้นได้
พร็อพเพอร์ตี้ timeline-scope ใช้ได้ทั้งกับไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมอง
การสาธิตและแหล่งข้อมูลเพิ่มเติม
แสดงตัวอย่างทั้งหมดในบทความนี้ในมินิไซต์ scroll-driven-animations.style เว็บไซต์มีตัวอย่างอีกมากมายเพื่อแสดงให้เห็นว่าภาพเคลื่อนไหวที่ทำงานตามการเลื่อนทำได้หลายอย่าง
ตัวอย่างเพลงอีกรายการหนึ่งคือรายการภาพปกอัลบั้มนี้ โดยภาพปกแต่ละภาพจะหมุนเป็น 3 มิติขณะอยู่ในจุดสนใจตรงกลาง
✨ ลองใช้ด้วยตัวคุณเอง
หรือดูการสาธิตการซ้อนการ์ดนี้ที่ใช้ประโยชน์จาก position: sticky เมื่อการ์ดซ้อนกัน การ์ดที่วางไว้แล้วจะมีขนาดลดลง ซึ่งจะสร้างเอฟเฟกต์ความลึกที่น่าสนใจ สุดท้ายแล้ว กองภาพทั้งหมดจะเลื่อนออกไปจากมุมมองพร้อมกัน
✨ ลองใช้ด้วยตัวคุณเอง
นอกจากนี้ scroll-driven-animations.style ยังมีคอลเล็กชันเครื่องมือต่างๆ เช่น ภาพแสดงผลความคืบหน้าของช่วงไทม์ไลน์ของมุมมองที่รวมไว้ก่อนหน้านี้ในโพสต์นี้
ภาพเคลื่อนไหวที่ทำงานตามการเลื่อนยังอยู่ในหัวข้อมีอะไรใหม่ในภาพเคลื่อนไหวบนเว็บที่ Google I/O ’23 ด้วย
