IntersectionObserver
IntersectionObserver
IntersectionObserver介绍
IntersectionObserver 是一个浏览器 API,用于异步观察目标元素与其祖先元素或视口的交叉状态。它非常适合实现以下功能:
- 懒加载图片或其他内容
- 无限滚动
- 检测广告曝光
- 根据用户是否查看内容来执行任务或动画
基本用法
// 创建一个 observer 实例
const observer = new IntersectionObserver(callback, options);
// 开始观察一个目标元素
observer.observe(targetElement);
详细步骤
- 创建观察者
const observer = new IntersectionObserver((entries, observer) => {
// entries 是 IntersectionObserverEntry 对象的数组
entries.forEach(entry => {
// 当目标元素与视口交叉时
if (entry.isIntersecting) {
console.log('元素进入视口');
// 如果只需要触发一次,可以停止观察
// observer.unobserve(entry.target);
} else {
console.log('元素离开视口');
}
});
}, options);
- 配置选项
const options = {
root: null, // 默认为视口,也可以是任何祖先元素
rootMargin: '0px', // 类似 CSS margin,可以扩大或缩小 root 元素的边界
threshold: 0.5 // 目标元素有 50% 进入 root 时触发回调
};
- 开始观察目标元素
// 单个元素
const target = document.querySelector('.my-element');
observer.observe(target);
// 或多个元素
const targets = document.querySelectorAll('.my-elements');
targets.forEach(target => observer.observe(target));
- 停止观察
// 停止观察特定元素
observer.unobserve(target);
// 停止观察所有元素并释放 observer
observer.disconnect();
实际应用示例
图片懒加载
<img class="lazy" data-src="image.jpg" alt="懒加载图片">
document.addEventListener('DOMContentLoaded', () => {
const lazyImages = document.querySelectorAll('img.lazy');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => imageObserver.observe(img));
});
无限滚动
const infiniteScroll = new IntersectionObserver((entries) => {
// 当底部元素可见时
if (entries[0].isIntersecting) {
loadMoreContent();
}
}, {
rootMargin: '100px' // 提前 100px 触发加载
});
infiniteScroll.observe(document.querySelector('#scroll-trigger'));
元素动画
const animationObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate');
} else {
// 如果希望元素离开视口时移除动画
// entry.target.classList.remove('animate');
}
});
}, {
threshold: 0.1 // 10% 可见时触发
});
document.querySelectorAll('.animate-on-scroll').forEach(el => {
animationObserver.observe(el);
});
