Intersection Observer là một trong những API có lẽ được mọi người yêu thích và có thể sử dụng trong tất cả các trình duyệt chính. Nhà phát triển đã sử dụng API này cho nhiều trường hợp sử dụng, bao gồm tải hình ảnh và video theo yêu cầu, thông báo khi các phần tử đạt đến position: sticky, kích hoạt các sự kiện phân tích và nhiều trường hợp khác.
Ở dạng cơ bản nhất, đây là giao diện của Intersection Observer API phiên bản 1:
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'));
Các vấn đề về khả năng hiển thị trong Intersection Observer phiên bản 1
Với Intersection Observer API phiên bản 1, bạn có thể biết thời điểm một phần tử được cuộn vào khung hiển thị của cửa sổ. Tuy nhiên, bạn không thể xác định liệu phần tử đó có bị nội dung khác trên trang che khuất hay không (còn gọi là tình trạng che khuất), hoặc liệu phần tử đó có xuất hiện dưới dạng được CSS sửa đổi hay không, chẳng hạn như transform, opacity hoặc filter. Những phần tử này có thể khiến phần tử đó không xuất hiện.
Đối với một phần tử trong tài liệu cấp cao nhất, thông tin này có thể được xác định bằng cách phân tích DOM bằng JavaScript, chẳng hạn như bằng DocumentOrShadowRoot.elementFromPoint().
Ngược lại, bạn không thể lấy được thông tin tương tự nếu phần tử có liên quan nằm trong iframe của bên thứ ba.
Tại sao khả năng hiển thị lại quan trọng?
Rất tiếc, Internet có những đối tượng xấu. Ví dụ: một nhà xuất bản không trung thực có thể sử dụng quảng cáo trả cho mỗi lượt nhấp trên một trang web. Họ có thể lừa người dùng nhấp vào những quảng cáo này để kiếm thêm tiền, ít nhất là cho đến khi mạng quảng cáo phát hiện ra thủ đoạn của họ. Thông thường, những quảng cáo như vậy được phân phát trong iframe.
Để đánh lừa người dùng, nhà xuất bản có thể làm cho iframe quảng cáo hoàn toàn trong suốt bằng CSS: iframe { opacity: 0; }. Sau đó, họ có thể đặt các iframe trong suốt này lên nội dung hấp dẫn, chẳng hạn như video về một chú mèo dễ thương mà người dùng muốn nhấp vào.
Đây được gọi là tấn công bằng cách nhấp chuột giả mạo.
Bạn có thể thấy một cuộc tấn công bằng cách nhấp vào một phần tử giả đang hoạt động trong phần trên của bản minh hoạ. Hãy thử "xem" video về mèo và kích hoạt chế độ đánh lừa. Quảng cáo trong iframe sẽ ghi nhận các lượt nhấp là hợp lệ, ngay cả khi bạn (vô tình) nhấp vào quảng cáo đó trong khi iframe đang ở trạng thái trong suốt.

Những cải tiến trong Intersection Observer phiên bản 2
Intersection Observer phiên bản 2 có thể theo dõi "khả năng hiển thị" của một phần tử theo cách mà con người xác định. Nếu bạn đặt một lựa chọn trong hàm tạo IntersectionObserver, các thực thể IntersectionObserverEntry thu được sẽ bao gồm một trường boolean mới có tên là isVisible. Khi isVisible là true, trình duyệt đảm bảo rằng thành phần này hoàn toàn không bị nội dung khác che khuất và không có hiệu ứng hình ảnh nào ẩn hoặc thay đổi màn hình của thành phần. Nếu isVisible là false, thì trình duyệt không thể đảm bảo điều đó.
Thông số kỹ thuật cho phép âm tính giả: isVisible có thể là false ngay cả khi phần tử thực sự hiển thị và không thay đổi. Để có hiệu suất tốt, các trình duyệt sử dụng các phép tính đơn giản hơn, chẳng hạn như hộp giới hạn và hình chữ nhật, đồng thời không kiểm tra từng pixel để biết các chi tiết phức tạp như border-radius.
Tuy nhiên, bạn không được phép có kết quả dương tính giả trong mọi trường hợp. Điều này có nghĩa là isVisible sẽ không phải là true nếu phần tử không hiển thị hoàn toàn và không được sửa đổi.
Áp dụng các thay đổi này
Hàm khởi tạo IntersectionObserver hiện lấy thêm 2 thuộc tính cấu hình:
delaylà một số cho biết độ trễ tối thiểu (tính bằng mili giây) giữa các thông báo từ đối tượng theo dõi, đối với một mục tiêu nhất định.trackVisibilitylà một giá trị boolean cho biết liệu đối tượng tiếp nhận dữ liệu có theo dõi các thay đổi về khả năng hiển thị của mục tiêu hay không.
Khi trackVisibility là true, bạn phải đặt delay thành 100 hoặc một giá trị cao hơn (tức là không quá một thông báo sau mỗi 100 mili giây).
Vì khả năng hiển thị tốn nhiều tài nguyên để tính toán, nên đây là biện pháp phòng ngừa nhằm tránh tình trạng giảm hiệu suất và tiêu thụ pin. Nhà phát triển có trách nhiệm nên sử dụng giá trị lớn nhất có thể chấp nhận được cho độ trễ.
Spec tính toán khả năng hiển thị. Giống như với phiên bản 1, khi thuộc tính trackVisibility của trình quan sát là false, mục tiêu được coi là hiển thị
Trong phiên bản 2, mục tiêu được coi là không nhìn thấy được nếu:
Nó có ma trận biến đổi hiệu quả, ngoài bản dịch 2D hoặc tỷ lệ tăng 2D.
Mục tiêu hoặc bất kỳ phần tử nào trong chuỗi khối chứa mục tiêu đó đều có độ mờ hiệu quả nhỏ hơn 1.0.
Mục tiêu hoặc bất kỳ phần tử nào trong chuỗi khối chứa mục tiêu đó đều có bộ lọc được áp dụng.
Nếu quá trình triển khai không đảm bảo rằng mục tiêu hoàn toàn không bị nội dung khác trên trang che khuất.
Điều này có nghĩa là các hoạt động triển khai hiện tại khá thận trọng trong việc đảm bảo khả năng hiển thị. Ví dụ: việc áp dụng một bộ lọc thang độ xám gần như không nhận thấy được (filter: grayscale(0.01%)) hoặc đặt độ trong suốt nhỏ nhất (opacity: 0.99) sẽ khiến phần tử không hiển thị.
Dưới đây là một đoạn mã mẫu minh hoạ các tính năng mới của API. Bạn có thể thấy logic theo dõi lượt nhấp của video này trong phần thứ hai của bản minh hoạ. Hãy thử "xem" video về chú cún. Kích hoạt chế độ tua nhanh để chuyển đổi chính bạn thành một đối tượng xấu và xem cách Intersection Observer phiên bản 2 ngăn chặn việc theo dõi các lượt nhấp không hợp lệ vào quảng cáo. Intersection Observer phiên bản 2 bảo vệ chúng ta.

<!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 v2, fallback 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'));
Tài nguyên khác
- Bản nháp đang được xử lý của Intersection Observer.
- Intersection Observer phiên bản 2 trên Trạng thái của nền tảng Chrome.
Lời cảm ơn
Cảm ơn Simeon Vincent, Yoav Weiss và Mathias Bynens đã xem xét, cũng như Stefan Zager đã xem xét và triển khai tính năng này trong Chrome.