ลบฟังก์ชันการหมดเวลาและกำจัดข้อบกพร่องออกไป เหตุการณ์ที่คุณต้องการจริงๆ คือ scrollend
ก่อนที่จะมีเหตุการณ์ scrollend ไม่มีวิธีที่เชื่อถือได้ในการตรวจจับว่าการเลื่อนเสร็จสมบูรณ์แล้ว ซึ่งหมายความว่าเหตุการณ์จะเริ่มทำงานช้าหรือขณะที่นิ้วของผู้ใช้ยังคงแตะอยู่บนหน้าจอ ความไม่แน่นอนในการทราบว่าการเลื่อนสิ้นสุดลงเมื่อใดทำให้เกิดข้อบกพร่องและประสบการณ์ที่ไม่ดีสำหรับผู้ใช้
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
สิ่งที่ดีที่สุดที่กลยุทธ์ setTimeout() นี้ทำได้คือการทราบว่าการเลื่อนหยุดลงเป็นเวลา 100ms หรือไม่ ซึ่งทำให้เหตุการณ์นี้คล้ายกับเหตุการณ์การเลื่อนหยุดชั่วคราว ไม่ใช่เหตุการณ์การเลื่อนสิ้นสุดลง
หลังจากเหตุการณ์ scrollend เบราว์เซอร์จะทำการประเมินที่ซับซ้อนทั้งหมดนี้ให้คุณ
document.onscrollend = event => {…}
นั่นแหละคือสิ่งดีๆ ซึ่งมีจังหวะเวลาที่สมบูรณ์แบบและเต็มไปด้วยเงื่อนไขที่มีความหมายก่อนที่จะปล่อยออกมา
ลองใช้งาน
รายละเอียดเหตุการณ์
เหตุการณ์ scrollend จะเริ่มทำงานเมื่อ
- เบราว์เซอร์ไม่แสดงภาพเคลื่อนไหวหรือแปลการเลื่อนอีกต่อไป
- ผู้ใช้ปล่อยมือแล้ว
- ตัวชี้ของผู้ใช้ปล่อยแถบเลื่อนแล้ว
- ผู้ใช้ปล่อยปุ่มที่กดแล้ว
- เลื่อนไปยังส่วนย่อยเสร็จสมบูรณ์แล้ว
- การสแนปการเลื่อนเสร็จสมบูรณ์แล้ว
- scrollTo() เสร็จสมบูรณ์แล้ว
- ผู้ใช้เลื่อนวิวพอร์ตภาพ
เหตุการณ์ scrollend จะไม่เริ่มทำงานในกรณีต่อไปนี้
- ท่าทางสัมผัสของผู้ใช้ไม่ได้ส่งผลให้เกิดการเปลี่ยนแปลงตำแหน่งการเลื่อน (ไม่มีการแปลเกิดขึ้น)
- scrollTo() ไม่ได้ส่งผลให้เกิดการแปลใดๆ
สาเหตุที่กิจกรรมนี้ใช้เวลานานมากในการมาถึงแพลตฟอร์มเว็บก็เนื่องมาจากรายละเอียดเล็กๆ น้อยๆ จำนวนมากที่ต้องระบุรายละเอียดข้อมูลจำเพาะ หนึ่งในส่วนที่ซับซ้อนที่สุดคือการอธิบายรายละเอียด scrollend สำหรับวิวพอร์ตภาพเทียบกับเอกสาร ลองนึกถึงหน้าเว็บที่คุณซูมเข้า คุณสามารถเลื่อนไปรอบๆ ได้เมื่ออยู่ในสถานะซูมนี้ และไม่จำเป็นต้องเลื่อนเอกสาร โปรดมั่นใจได้ว่าแม้แต่การโต้ตอบการเลื่อนที่ขับเคลื่อนโดยผู้ใช้ในวิวพอร์ตภาพนี้ก็จะส่งเหตุการณ์ scrollend เมื่อเสร็จสมบูรณ์
การใช้กิจกรรม
คุณสามารถลงทะเบียน Listener ได้หลายวิธีเช่นเดียวกับเหตุการณ์การเลื่อนอื่นๆ
addEventListener("scrollend",> (event) = {
// scroll ended
});
aScrollingElement.addEventListener("scroll>end", (event) = {
// scroll ended
});
หรือใช้พร็อพเพอร์ตี้เหตุการณ์ต่อไปนี้
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
Polyfill และการเพิ่มประสิทธิภาพแบบต่อเนื่อง
หากคุณต้องการใช้เหตุการณ์ใหม่นี้ในตอนนี้ เราขอแนะนำให้ทำดังนี้ คุณสามารถใช้กลยุทธ์การสิ้นสุดการเลื่อนปัจจุบันต่อไปได้ (หากมี) และตรวจสอบการรองรับที่จุดเริ่มต้นของกลยุทธ์ด้วยวิธีต่อไปนี้
'onscrollend' in window
// true, if available
ซึ่งจะรายงานเป็นจริงหรือเท็จ โดยขึ้นอยู่กับว่าเบราว์เซอร์มีเหตุการณ์หรือไม่ การตรวจสอบนี้ช่วยให้คุณแยกสาขาโค้ดได้ ดังนี้
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll => event = {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
ซึ่งถือเป็นการเริ่มต้นที่ดีในการปรับปรุงเหตุการณ์ scrollend อย่างต่อเนื่องเมื่อพร้อมใช้งาน คุณยังลองใช้ polyfill (NPM) ที่ฉันสร้างขึ้นซึ่งทำงานได้ดีที่สุดเท่าที่เบราว์เซอร์จะทำได้ ดังนี้
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
Polyfill จะปรับปรุงโดยใช้การเพิ่มประสิทธิภาพแบบต่อเนื่องเพื่อใช้เหตุการณ์ scrollend ในตัวของเบราว์เซอร์ หากมี หากไม่มี สคริปต์จะดูเหตุการณ์เคอร์เซอร์และเลื่อนเพื่อประมาณการสิ้นสุดเหตุการณ์ให้ดีที่สุดเท่าที่จะทำได้
กรณีการใช้งาน
แนวทางปฏิบัติแนะนำคือหลีกเลี่ยงการทำงานที่ต้องใช้การประมวลผลสูงขณะที่กำลังเลื่อน แนวทางปฏิบัตินี้ช่วยให้การเลื่อนใช้หน่วยความจำและการประมวลผลได้มากเท่าที่ต้องการเพื่อให้ประสบการณ์การใช้งานเป็นไปอย่างราบรื่น การใช้เหตุการณ์ scrollend เป็นช่วงเวลาที่เหมาะอย่างยิ่งในการเรียกใช้และทำงานหนัก เนื่องจากไม่มีการเลื่อนอีกต่อไป
คุณสามารถใช้เหตุการณ์ scrollend เพื่อทริกเกอร์การดำเนินการต่างๆ ได้ Use Case ทั่วไปคือการซิงค์องค์ประกอบ UI ที่เชื่อมโยงกับตำแหน่งที่การเลื่อนหยุดลง เช่น
- การซิงค์ตำแหน่งการเลื่อนภาพสไลด์กับสัญญาณบอกสถานะแบบจุด
- ซิงค์รายการในแกลเลอรีกับข้อมูลเมตา
- ดึงข้อมูลหลังจากที่ผู้ใช้เลื่อนไปยังแท็บใหม่
ลองนึกภาพสถานการณ์ เช่น ผู้ใช้ปัดอีเมลทิ้ง หลังจากที่ผู้ใช้ปัดเสร็จแล้ว คุณจะดำเนินการตามตำแหน่งที่ผู้ใช้เลื่อนไปได้
นอกจากนี้ คุณยังใช้เหตุการณ์นี้เพื่อซิงค์หลังจากการเลื่อนแบบเป็นโปรแกรมหรือการเลื่อนของผู้ใช้ หรือการดำเนินการต่างๆ เช่น การบันทึกข้อมูลวิเคราะห์ได้ด้วย
ต่อไปนี้เป็นตัวอย่างที่ดีซึ่งต้องอัปเดตองค์ประกอบหลายอย่าง เช่น ลูกศร จุด และโฟกัส ตามตำแหน่งการเลื่อน ดูวิธีที่ฉันสร้างภาพสไลด์นี้บน YouTube นอกจากนี้ ให้ลองใช้เดโมแบบสด
ขอขอบคุณ Mehdi Kazemi สำหรับงานด้านวิศวกรรมในเรื่องนี้ และ Robert Flack สำหรับคำแนะนำเกี่ยวกับ API และการติดตั้งใช้งาน