Intersection Observer API
Bài viết được sự cho phép của tác giả Lưu Bình An
Chúng ta thường phải đặt listener
trên sự kiện window.scroll
thực hiện một số thao tác tính toán, so sánh với thanh scroll để biết được khi nào element bắt đầu xuất hiện.
Cách làm này gây nhiều vấn đề hiệu năng và tương đối rườm rà. Giờ các trình duyệt đã đồng loạt hỗ trợ Intersection Observer API, chúng ta có một cách hoàn toàn gọn gàng, sạch sẽ mà lại tối ưu hiệu năng hơn nhiều.
Cách sử dụng như sau, chúng ta khởi tạo một instance IntersectionObserver
và gọi observe
trên element muốn theo dõi (watch là thuật ngữ chuyên ngành hơn)
const myImg = document.querySelector('.animate-me');
const observer = new IntersectionObserver((entry, observer) => {
console.log({ entry });
console.log({ observer });
})
observer.observe(myImg);
Trong trường hợp chúng ta muốn observe trên nhiều element cùng lúc
const myImgs = document.querySelectorAll('.animate-me');
const observer = new IntersectionObserver(entries => {
console.log(entries);
});
myImgs.forEach(image => {
observer.observe(image);
});
Để thực thi một tác vụ nào đó khi element bắt đầu xuất hiện trong viewport hoặc leave khỏi viewport
const myImgs = document.querySelectorAll('.animate-me');
observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
console.log('in the view');
} else {
console.log('out of view');
}
});
});
myImgs.forEach(image => {
observer.observe(image);
});
Với điều kiện intersectionRatio > 0
chúng ta biết được element đã xuất hiện trong viewport hay không
Với lazy load, chúng ta chỉ cần observe ở lần đầu tiên khi xuất hiện trên viewport, chúng ta sẽ unobserve
nó đi vì không cần tracking tiếp nữa
const myImgs = document.querySelectorAll('.animate-me');
observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
console.log('in the view');
observer.unobserve(entry.target);
} else {
console.log('out of view');
}
});
});
myImgs.forEach(image => {
observer.observe(image);
});
IntersectionObserver
API nhận thêm params thứ 2, để chúng ta truyền một số config
const config = {
rootMargin: '50px 20px 75px 30px',
threshold: [0, 0.25, 0.75, 1]
};
const observer = new IntersectionObserver(entry => {
// ...
}, config);
Các giá trị có thể truyền vào cho config
root
element dùng để kiểm tra intersection, nếunull
nó sẽ lấydocument
viewportrootMargin
: khai báo như giá trị margin css, ví dụ3rem 2rem
, có thể dùng để thêmoffset
cho intersection pointthrehold
: mảng giá trị từ 0 đến 1, tương ứng với ratio xuất hiện của element, 0 = hoàn toàn ra khỏi viewport, 1 là đang nằm trong viewport hoàn toàn,callback
sẽ được gọi vào tất cả các giá trị đã khai báo
Element được xem là nằm ngoài viewport khi nó đã nằm ngoài viewport + 15px margin
Ứng dụng 1: lazy load image
let observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
/* Placeholder replacement */
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
});
},
{rootMargin: "0px 0px -200px 0px"});
document.querySelectorAll('img').forEach(img => { observer.observe(img) });
Ứng dụng 2: Tự động pause video khi ra khỏi màn hình
let video = document.querySelector('video');
let isPaused = false; /* Flag for auto-paused video */
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.intersectionRatio!=1 && !video.paused){
video.pause(); isPaused = true;
}
else if(isPaused) {video.play(); isPaused=false}
});
}, {threshold: 1});
observer.observe(video);
Ứng dụng 3: Toggle class khi header sticky
const primaryNav = document.getElementById('primaryNav');
function callBack ([e]) {
e.target.classList.toggle("sticky", e.intersectionRatio < 1)
}
const observer = new IntersectionObserver(
callBack,
{ threshold: [1] }
);
observer.observe(primaryNav)
@media (prefers-reduced-motion: no-preference) {
.scroller {
scroll-behavior: smooth;
}
}
Tham khảo
- https://alligator.io/js/intersection-observer/
- https://css-tricks.com/a-few-functional-uses-for-intersection-observer-to-know-when-an-element-is-in-view/
- https://www.smashingmagazine.com/2021/07/dynamic-header-intersection-observer/
Bài viết gốc được đăng tải tại vuilaptrinh.com
Có thể bạn quan tâm:
- Angular – Tự xây dựng module “lazy load images”
- Kiến thức về “Lazy-loading images” mà bạn cần biết
- 6 ví dụ để bạn yêu luôn observable
Xem thêm Việc làm IT hấp dẫn trên TopDev
- B BenQ RD Series – Dòng Màn Hình Lập Trình 4k+ Đầu Tiên Trên Thế Giới
- i iOS 18 có gì mới? Có nên cập nhật iOS 18 cho iPhone của bạn?
- G Gamma AI là gì? Cách tạo slide chuyên nghiệp chỉ trong vài phút
- P Power BI là gì? Vì sao doanh nghiệp nên sử dụng PBI?
- K KICC HCMC x TOPDEV – Bước đệm nâng tầm sự nghiệp cho nhân tài IT Việt Nam
- T Trello là gì? Cách sử dụng Trello để quản lý công việc
- T TOP 10 SỰ KIỆN CÔNG NGHỆ THƯỜNG NIÊN KHÔNG NÊN BỎ LỠ
- T Tìm hiểu Laptop AI – So sánh Laptop AI với Laptop thường
- M MySQL vs MS SQL Server: Phân biệt hai RDBMS phổ biến nhất
- S SearchGPT là gì? Công cụ tìm kiếm mới có thể đánh bại Google?