IntersectionObserver

Pcjmy2025-03-09JavaScriptJavaScript

IntersectionObserver

IntersectionObserver介绍

IntersectionObserver 是一个浏览器 API,用于异步观察目标元素与其祖先元素或视口的交叉状态。它非常适合实现以下功能:

  • 懒加载图片或其他内容
  • 无限滚动
  • 检测广告曝光
  • 根据用户是否查看内容来执行任务或动画

基本用法

// 创建一个 observer 实例
const observer = new IntersectionObserver(callback, options);

// 开始观察一个目标元素
observer.observe(targetElement);

详细步骤

  1. 创建观察者
const observer = new IntersectionObserver((entries, observer) => {
  // entries 是 IntersectionObserverEntry 对象的数组
  entries.forEach(entry => {
    // 当目标元素与视口交叉时
    if (entry.isIntersecting) {
      console.log('元素进入视口');
      
      // 如果只需要触发一次,可以停止观察
      // observer.unobserve(entry.target);
    } else {
      console.log('元素离开视口');
    }
  });
}, options);
  1. 配置选项
const options = {
  root: null, // 默认为视口,也可以是任何祖先元素
  rootMargin: '0px', // 类似 CSS margin,可以扩大或缩小 root 元素的边界
  threshold: 0.5 // 目标元素有 50% 进入 root 时触发回调
};
  1. 开始观察目标元素
// 单个元素
const target = document.querySelector('.my-element');
observer.observe(target);

// 或多个元素
const targets = document.querySelectorAll('.my-elements');
targets.forEach(target => observer.observe(target));
  1. 停止观察
// 停止观察特定元素
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);
});
Last Updated 2025/3/9 23:59:36