ดูวิธีใช้ไทม์ไลน์การเลื่อนและไทม์ไลน์มุมมองเพื่อสร้างภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนในลักษณะการประกาศ
เผยแพร่: 5 พฤษภาคม 2023
ภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน
ภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนเป็นรูปแบบ 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% เมื่อเลื่อนแถบเลื่อนจากบนลงล่าง
✨ ลองด้วยตัวคุณเอง
ไทม์ไลน์ความคืบหน้าในการเลื่อนมักเรียกสั้นๆ ว่า "ไทม์ไลน์การเลื่อน"
ดูไทม์ไลน์ความคืบหน้า
ไทม์ไลน์ประเภทนี้จะลิงก์กับความคืบหน้าแบบสัมพัทธ์ขององค์ประกอบหนึ่งๆ ภายในคอนเทนเนอร์เลื่อน ระบบจะติดตามออฟเซ็ตการเลื่อนของผู้เลื่อนเช่นเดียวกับไทม์ไลน์ความคืบหน้าในการเลื่อน ซึ่งต่างจากไทม์ไลน์ความคืบหน้าในการเลื่อนตรงที่ตำแหน่งสัมพัทธ์ของออบเจ็กต์ภายในตัวเลื่อนนั้นจะเป็นตัวกำหนดความคืบหน้า
ซึ่งคล้ายกับวิธีที่ 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: ใช้ Viewport ของเอกสารเป็นคอนเทนเนอร์การเลื่อน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
อีกวิธีในการกำหนดไทม์ไลน์ความคืบหน้าในการเลื่อนคือการใช้ไทม์ไลน์ที่มีชื่อ ซึ่งอาจจะยาวกว่าเล็กน้อย แต่ก็มีประโยชน์ในกรณีที่คุณไม่ได้กำหนดเป้าหมายไปยังตัวเลื่อนหลักหรือตัวเลื่อนรูท หรือเมื่อหน้าเว็บใช้ไทม์ไลน์หลายรายการ หรือเมื่อการค้นหาอัตโนมัติไม่ทำงาน วิธีนี้จะช่วยให้คุณระบุไทม์ไลน์ความคืบหน้าในการเลื่อนได้ตามชื่อที่ตั้งไว้
หากต้องการสร้างไทม์ไลน์ความคืบหน้าในการเลื่อนที่มีชื่อในองค์ประกอบ ให้ตั้งค่าพร็อพเพอร์ตี้ 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: กำหนดแกนที่จะติดตาม ค่าที่ยอมรับจะเหมือนกับตัวแปร CSS คือblock,inline,xและy
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: ดูช่วงไทม์ไลน์
โดยค่าเริ่มต้น ภาพเคลื่อนไหวที่ลิงก์กับไทม์ไลน์ของมุมมองจะแนบกับช่วงไทม์ไลน์ทั้งหมด โดยจะเริ่มตั้งแต่ช่วงที่วัตถุกำลังจะเข้าสู่ Scrollport และสิ้นสุดเมื่อวัตถุออกจาก Scrollport ทั้งหมดแล้ว
นอกจากนี้ คุณยังลิงก์ไปยังส่วนที่เฉพาะเจาะจงของไทม์ไลน์การดูได้ด้วยการระบุช่วงที่ควรแนบ เช่น เมื่อวัตถุเข้าสู่แถบเลื่อนเท่านั้น ในภาพด้านล่าง ความคืบหน้าจะเริ่มนับจาก 0% เมื่อวัตถุเข้าสู่คอนเทนเนอร์เลื่อน แต่จะไปถึง 100% ตั้งแต่ช่วงเวลาที่วัตถุตัดกันทั้งหมด
ช่วงไทม์ไลน์การดูที่เป็นไปได้ซึ่งคุณกำหนดเป้าหมายได้มีดังนี้
cover: แสดงช่วงทั้งหมดของไทม์ไลน์ความคืบหน้าในการดูentry: แสดงช่วงเวลาที่ช่องหลักกำลังเข้าสู่ช่วงการมองเห็นความคืบหน้าในการดูexit: แสดงช่วงเวลาที่ช่องหลักกำลังออกจากช่วงการมองเห็นความคืบหน้าในการดูentry-crossing: แสดงช่วงเวลาที่กรอบหลักข้ามขอบเขตสิ้นสุดexit-crossing: แสดงช่วงที่กรอบหลักข้ามขอบเขตเริ่มต้นcontain: แสดงช่วงที่กล่องหลักมีขอบเขตครอบคลุมทั้งหมด หรือครอบคลุมทั้งหมดในช่วงการมองเห็นความคืบหน้าในการดูภายใน Scrollport ซึ่งขึ้นอยู่กับว่าตัวแบบสูงกว่าหรือต่ำกว่าผู้เลื่อน
หากต้องการกำหนดช่วง คุณต้องตั้งค่า range-start และ range-end โดยแต่ละรายการประกอบด้วยชื่อช่วง (ดูรายการด้านบน) และออฟเซ็ตช่วงเพื่อกำหนดตำแหน่งภายในชื่อช่วงนั้น โดยปกติแล้วออฟเซ็ตช่วงจะเป็นเปอร์เซ็นต์ตั้งแต่ 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% จากนั้นลากแถบเลื่อนเพื่อดูผลลัพธ์ของภาพเคลื่อนไหว
ดูการบันทึก
ขณะที่ลองใช้เครื่องมือช่วงไทม์ไลน์ของมุมมองนี้ คุณอาจสังเกตเห็นว่าช่วงบางช่วงสามารถกำหนดเป้าหมายได้โดยใช้ชุดค่าผสมชื่อช่วง + ออฟเซ็ตช่วง 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: แกนที่จะติดตาม ค่าที่ยอมรับจะเหมือนกับตัวแปร CSS คือblock,inline,xและyinset: การปรับ(บวก)หรือ(ลบ)ของขอบเขตการเลื่อนเมื่อพิจารณาว่ากล่องอยู่ในมุมมองหรือไม่
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 ชุด
มาดูตัวอย่างรายชื่อติดต่อนี้กัน ซึ่งรายการในรายชื่อจะมีการเคลื่อนไหว เมื่อรายการในลิสต์เข้าสู่ Scrollport จากด้านล่าง รายการจะเลื่อน+จางลง และเมื่อออกจาก Scrollport ที่ด้านบน รายการจะเลื่อน+จางลง
✨ ลองด้วยตัวคุณเอง
สำหรับการสาธิตนี้ องค์ประกอบแต่ละรายการจะได้รับการตกแต่งด้วยไทม์ไลน์ของ View 1 รายการที่ติดตามองค์ประกอบเมื่อข้าม Scrollport แต่มีภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน 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 ใช้ได้กับทั้งไทม์ไลน์การเลื่อนและไทม์ไลน์การดู
การสาธิตและแหล่งข้อมูลเพิ่มเติม
การสาธิตทั้งหมดที่กล่าวถึงในบทความนี้อยู่ในมินิไซต์ scroll-driven-animations.style เว็บไซต์มีเดโมอื่นๆ อีกมากมายเพื่อเน้นย้ำถึงสิ่งที่ทำได้ด้วยภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อน
ตัวอย่างเพิ่มเติมอย่างหนึ่งคือรายการปกอัลบั้มนี้ โดยปกแต่ละปกจะหมุนในรูปแบบ 3 มิติเมื่อได้รับสปอตไลต์ตรงกลาง
✨ ลองด้วยตัวคุณเอง
หรือการสาธิตการซ้อนการ์ดนี้ที่ใช้ประโยชน์จาก position: sticky เมื่อมีการซ้อนการ์ด การ์ดที่ซ้อนอยู่แล้วจะเล็กลง ทำให้เกิดเอฟเฟกต์ความลึกที่สวยงาม สุดท้ายแล้ว สแต็กทั้งหมดจะเลื่อนออกไปจากมุมมองเป็นกลุ่ม
✨ ลองด้วยตัวคุณเอง
นอกจากนี้ scroll-driven-animations.style ยังมีชุดเครื่องมือต่างๆ เช่น การแสดงภาพความคืบหน้าของช่วงไทม์ไลน์ของมุมมอง ซึ่งรวมอยู่ในโพสต์นี้ก่อนหน้านี้
นอกจากนี้ มีอะไรใหม่ใน Web Animations ที่งาน Google I/O ’23 ยังครอบคลุมภาพเคลื่อนไหวที่ขับเคลื่อนด้วยการเลื่อนด้วย