ดูวิธีใช้ไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมองเพื่อสร้างภาพเคลื่อนไหวที่ทำงานตามการเลื่อนในลักษณะที่ประกาศ
เผยแพร่: 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
ซึ่งคล้ายกับตัวแปร CSSinset
: การปรับแถบเลื่อน(บวก) หรือ(ลบ) ของแถบเลื่อนเมื่อพิจารณาว่ากล่องอยู่ในมุมมองหรือไม่
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
ผลลัพธ์ที่ได้จะเหมือนกับก่อนหน้านี้ทุกประการ
✨ ลองใช้ด้วยตัวคุณเอง
การแนบกับไทม์ไลน์การเลื่อนที่ไม่ใช่บรรพบุรุษ
กลไกการค้นหาสำหรับไทม์ไลน์การเลื่อนที่มีชื่อและไทม์ไลน์มุมมองที่มีชื่อจะจำกัดอยู่ที่บรรพบุรุษของการเลื่อนเท่านั้น แต่บ่อยครั้ง องค์ประกอบที่ต้องเคลื่อนไหวนั้นไม่ได้เป็นองค์ประกอบย่อยของ Scroller ที่ต้องติดตาม
พร็อพเพอร์ตี้ 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 ด้วย