Intersection Observer v2 เพิ่มความสามารถในการสังเกตไม่เพียงเฉพาะจุดตัดเท่านั้น แต่ยังตรวจจับได้ด้วยว่ามีการแสดงองค์ประกอบที่ตัดกัน ณ เวลาที่มีการตัดกันหรือไม่
Intersection Observer v1 เป็น API หนึ่งที่อาจจะเป็นที่นิยมกันทุกคน และเนื่องจากตอนนี้ Safari รองรับเช่นกัน และท้ายที่สุดแล้ว API นี้ยังสามารถใช้งานได้ทั่วทั้งเบราว์เซอร์หลักๆ ด้วย หากต้องการทบทวนข้อมูลเกี่ยวกับ API อย่างรวดเร็ว เราขอแนะนำให้ดูเคล็ดลับการเพิ่มประสิทธิภาพแบบเร่งด่วนของ Surma ใน Intersection Observer v1 ที่ฝังไว้ด้านล่าง
นอกจากนี้ คุณยังอ่านบทความเชิงลึกของ Surma ได้ด้วย
ผู้คนได้ใช้ Intersection Observer v1 สำหรับกรณีการใช้งานที่หลากหลาย เช่น การโหลดรูปภาพและวิดีโอแบบ Lazy Loading, รับการแจ้งเตือนเมื่อองค์ประกอบไปถึง position: sticky
, การเริ่มแสดงเหตุการณ์ Analytics และอื่นๆ อีกมากมาย
ดูรายละเอียดทั้งหมดได้ในเอกสาร Intersection Observer ใน MDN แต่ขอย้ำอีกครั้งว่า Intersection Observer v1 API มีลักษณะอย่างไรในกรณีพื้นฐานที่สุด
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Intersection Observer v1 มีข้อจํากัดอะไรบ้าง
ขออธิบายให้ชัดเจน Intersection Observer v1 นั้นยอดเยี่ยม แต่ยังไม่สมบูรณ์ มีบางกรณีที่ API ทำงานไม่ได้ มาดูรายละเอียดกัน
Intersection Observer v1 API สามารถบอกได้เมื่อมีการเลื่อนองค์ประกอบไปยังวิวพอร์ตของหน้าต่าง แต่จะไม่บอกคุณว่าองค์ประกอบถูกบดบังโดยเนื้อหาหน้าเว็บอื่นๆ หรือไม่ (นั่นคือเมื่อองค์ประกอบถูกบดบัง) หรือการแสดงผลภาพองค์ประกอบได้รับการแก้ไขโดยเอฟเฟกต์ภาพ เช่น transform
, opacity
, filter
หรือไม่ ซึ่งทำให้องค์ประกอบนั้นมองไม่เห็นได้อย่างมีประสิทธิภาพ
สําหรับองค์ประกอบในเอกสารระดับบนสุด ข้อมูลนี้สามารถระบุได้โดยการวิเคราะห์ DOM ผ่าน JavaScript เช่น ผ่าน DocumentOrShadowRoot.elementFromPoint()
แล้วเจาะลึกเพิ่มเติม
ในทางตรงกันข้าม คุณจะไม่สามารถรับข้อมูลเดียวกันได้หากองค์ประกอบที่เป็นปัญหานั้นอยู่ใน iframe ของบุคคลที่สาม
เหตุใดการแสดงผลจริงจึงสำคัญมาก
ขออภัยที่อินเทอร์เน็ตเป็นพื้นที่ที่ดึงดูดผู้ไม่ประสงค์ดีที่มีเจตนาร้าย
ตัวอย่างเช่น ผู้เผยแพร่โฆษณาที่ไม่น่าไว้วางใจซึ่งแสดงโฆษณาแบบจ่ายต่อคลิกในเว็บไซต์เนื้อหาอาจมีแรงจูงใจที่จะหลอกลวงผู้ใช้ให้คลิกโฆษณาเพื่อเพิ่มการชำระคืนโฆษณาของผู้เผยแพร่โฆษณา (อย่างน้อยก็ในระยะสั้นจนกว่าเครือข่ายโฆษณาจะจับได้)
โดยปกติแล้ว โฆษณาดังกล่าวจะแสดงใน iframe
หากผู้เผยแพร่โฆษณาต้องการให้ผู้ใช้คลิกโฆษณาดังกล่าว ก็อาจทําให้ iframe ของโฆษณาโปร่งใสได้โดยใช้กฎ CSS iframe { opacity: 0; }
และวางซ้อน iframe ไว้บนสิ่งที่น่าสนใจ เช่น วิดีโอแมวน่ารักที่ผู้ใช้อยากคลิกจริงๆ
การดำเนินการนี้เรียกว่าคลิกแจ็กกิ้ง
คุณสามารถดูการโจมตีด้วยคลิกเจตนาดังกล่าวได้ในส่วนบนของการสาธิตนี้ (ลอง "ดู" วิดีโอแมวและเปิดใช้งาน "โหมดกลโกง")
คุณจะเห็นว่าโฆษณาใน iframe "คิดว่า" ได้รับการคลิกที่ถูกต้อง แม้ว่าจะโปร่งแสงโดยสมบูรณ์เมื่อคุณ (แกล้งทำเป็น) คลิกก็ตาม
Intersection Observer v2 แก้ปัญหานี้ได้อย่างไร
Intersection Observer v2 นำเสนอแนวคิดในการติดตาม "การแสดงผล" จริงขององค์ประกอบเป้าหมายตามที่มนุษย์จะกำหนด
การตั้งค่าตัวเลือกในตัวสร้างIntersectionObserver
จะทำให้อินสแตนซ์ที่ตัดกันของ IntersectionObserverEntry
มีช่องบูลีนใหม่ชื่อ isVisible
ค่า true
สำหรับ isVisible
เป็นการรับประกันที่น่าเชื่อถือจากการใช้งานพื้นฐานว่าองค์ประกอบเป้าหมายไม่มีเนื้อหาอื่นมาจำกัดอย่างสมบูรณ์ และไม่ใช้เอฟเฟกต์ภาพที่อาจเปลี่ยนหรือบิดเบี้ยวการแสดงผลบนหน้าจอ
ในทางตรงกันข้าม ค่า false
หมายความว่าการติดตั้งใช้งานไม่สามารถรับประกันได้
รายละเอียดสำคัญของข้อกำหนดนี้คืออนุญาตให้ติดตั้งใช้งานการรายงานผลลบลวงได้ (กล่าวคือ การตั้งค่า isVisible
เป็น false
แม้ว่าองค์ประกอบเป้าหมายจะแสดงให้เห็นและไม่มีการแก้ไขเลยก็ตาม)
เบราว์เซอร์จะจำกัดการทำงานด้วยกล่องขอบเขตและเรขาคณิตแบบเส้นตรงเพื่อประสิทธิภาพหรือเหตุผลอื่นๆ โดยไม่พยายามทำให้ได้ผลลัพธ์ที่สมบูรณ์แบบแบบพิกเซลสำหรับการแก้ไข เช่น border-radius
อย่างไรก็ตาม ไม่อนุญาตให้ผลบวกลวงเกิดขึ้นไม่ว่าในกรณีใดก็ตาม (นั่นคือ การตั้งค่า isVisible
เป็น true
เมื่อองค์ประกอบเป้าหมายไม่แสดงอย่างสมบูรณ์และไม่มีการแก้ไข)
โค้ดใหม่มีลักษณะเป็นอย่างไรในทางปฏิบัติ
ตอนนี้เครื่องมือสร้าง IntersectionObserver
จะมีพร็อพเพอร์ตี้การกำหนดค่าเพิ่มเติมอีก 2 รายการ ได้แก่ delay
และ trackVisibility
delay
คือตัวเลขที่ระบุความล่าช้าขั้นต่ำเป็นมิลลิวินาทีระหว่างการแจ้งเตือนจากผู้สังเกตการณ์สําหรับเป้าหมายหนึ่งๆ
trackVisibility
คือบูลีนซึ่งระบุว่าผู้สังเกตจะติดตามการเปลี่ยนแปลงระดับการมองเห็นของเป้าหมายหรือไม่
โปรดทราบว่าเมื่อ trackVisibility
เป็น true
delay
ต้องมีค่าอย่างน้อย 100
(นั่นคือ มีการแจ้งเตือนไม่เกิน 1 ครั้งทุกๆ 100 มิลลิวินาที)
ดังที่กล่าวไว้ก่อนหน้านี้ การคำนวณการแสดงผลมีค่าใช้จ่ายสูง และข้อกําหนดนี้เป็นการป้องกันการเสื่อมประสิทธิภาพและการใช้แบตเตอรี่ นักพัฒนาซอฟต์แวร์ที่รับผิดชอบจะใช้มูลค่าที่ยอมรับได้สูงสุดสำหรับความล่าช้า
ข้อกําหนดปัจจุบันกําหนดให้คํานวณระดับการมองเห็นดังนี้
หากแอตทริบิวต์
trackVisibility
ของผู้สังเกตการณ์คือfalse
ระบบจะถือว่าเป้าหมายนั้นมองเห็นได้ ซึ่งสอดคล้องกับลักษณะการทํางานของ v1 ปัจจุบันหากเป้าหมายมีเมทริกซ์การเปลี่ยนรูปแบบที่มีประสิทธิภาพนอกเหนือจากการเปลี่ยนรูปแบบ 2 มิติหรือการขยายขนาด 2 มิติตามสัดส่วน ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากเป้าหมายหรือองค์ประกอบใดๆ ในเชนบล็อกที่ประกอบด้วยองค์ประกอบนั้นมีความทึบแสงที่มีประสิทธิภาพอื่นนอกเหนือจาก 1.0 ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากเป้าหมายหรือองค์ประกอบใดๆ ในเชนบล็อกที่ประกอบด้วยมีการใช้ตัวกรอง ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
หากการติดตั้งใช้งานไม่สามารถรับประกันได้ว่าเป้าหมายจะไม่ถูกบดบังโดยเนื้อหาอื่นๆ ของหน้าเว็บเลย ระบบจะถือว่าเป้าหมายนั้นมองไม่เห็น
ซึ่งหมายความว่าการใช้งานในปัจจุบันค่อนข้างเข้มงวดและรับประกันระดับการเข้าถึงได้
เช่น การใช้ฟิลเตอร์โทนสีเทาที่แทบมองไม่เห็น เช่น filter: grayscale(0.01%)
หรือการตั้งค่าความโปร่งใสที่แทบมองไม่เห็นด้วย opacity: 0.99
จะทำให้องค์ประกอบนั้นมองไม่เห็น
ด้านล่างนี้คือตัวอย่างโค้ดสั้นๆ ที่แสดงฟีเจอร์ API ใหม่ คุณดูการทำงานของตรรกะการติดตามการคลิกในส่วนที่ 2 ของเดโมได้ (แต่ตอนนี้ลอง "ดู" วิดีโอลูกสุนัข) อย่าลืมเปิดใช้งาน "โหมดกลโกง" อีกครั้งเพื่อเปลี่ยนตัวเองเป็นผู้เผยแพร่โฆษณาที่ไม่น่าไว้วางใจทันที และดูว่า Intersection Observer v2 ป้องกันไม่ให้มีการติดตามการคลิกโฆษณาที่เป็นการฉ้อโกงได้อย่างไร คราวนี้ Intersection Observer v2 จะช่วยเราได้ 🎉
<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
ลิงก์ที่เกี่ยวข้อง
- ฉบับร่างล่าสุดของข้อกำหนด Intersection Observer
- Intersection Observer v2 ในสถานะแพลตฟอร์ม Chrome
- ข้อบกพร่อง Chromium ของ Intersection Observer v2
- Blink ความตั้งใจในการติดตั้งใช้งานการโพสต์
ขอขอบคุณ
ขอขอบคุณ Simeon Vincent, Yoav Weiss และ Mathias Bynens ที่ช่วยอ่านบทความนี้ รวมถึงที่ Stefan Zager ตรวจสอบและนําฟีเจอร์นี้ไปใช้ใน Chrome ด้วย รูปภาพหลักโดย Sergey Semin ใน Unsplash