Skip to content

Intersection Observer

root: 用作视口的元素,用于检查目标的可见性。必须是目标的祖先。如果未指定或为 null,则默认为浏览器视口。

rootMargin: 根周围的边距。其值可以类似于 CSS margin 属性,例如 "10px 20px 30px 40px"(上、右、下、左)。这些值可以是百分比。在计算交叉点之前,这组值用于增大或缩小根元素边框的每一侧。默认值为全零。

threshold: 一个数字或一个数字数组,表示目标可见度达到多少百分比时,观察器的回调就应该执行。如果只想在能见度超过 50% 时检测,可以使用 0.5 的值。如果希望每次能见度超过 25% 时都执行回调,则需要指定数组 [0, 0.25, 0.5, 0.75, 1]。默认值为 0(这意味着只要有一个像素可见,回调就会运行)。值为 1.0 意味着在每个像素都可见之前,阈值不会被认为已通过。

图片懒加载

js
const ob = new IntersectionObserver(
  (entries) => {
    for (const entry of entries) {
      // 正在和视口交叉
      if (entry.isIntersecting) {
        const img = entry.target();
        img.src = img.dataset.src;
        // 取消监听
        ob.unobserve();
      }
    }
  },
  {
    // root: null,
    // rootMargin: null,
    threshold: 0,
  }
);

const imgs = document.querySelectorAll("img[data-src]");
imgs.forEach((img) => ob.observe(img));

无限滚动

思路:只要下方 loading 图进入视口(或者离视口有一定具体,即:提前加载),就加载指定数量的图片。

js
async function loadMoreImages(num = 10) {
  // 加载逻辑...
}

const ob = new IntersectionObserver(
  (entries) => {
    const entry = entries[0];
    if (entry.isIntersecting) {
      loadMoreImages();
    }
  },
  {
    // rootMargin: null,
    threshold: 0,
  }
);

ob.observe(document.querySelector(".spin"));

视频进入视口播放,离开后暂停

js
const vdo = document.querySelector("video");

const ob = new IntersectionObserver(
  (entries) => {
    const entry = entries[0];
    if (entry.isIntersecting) {
      vdo.play();
    } else {
      vdo.pause();
    }
  },
  {
    threshold: 0.8,
  }
);

ob.observe(vdo);