getBoundingClientRect 和 IntersectionObserver 的区别和用法

getBoundingClientRect

getBoundingClientRect 是一个 DOM API 方法,用于获取指定元素相对于视口的位置和尺寸信息。它返回一个 DOMRect 对象,包含了元素的左上角和右下角相对于视口的坐标。
“图片懒加载”,这个词语想必大家再熟悉不过了。传统的实现方法是,监听 scroll 事件,获取 img 元素相对于视口的顶点位置 el.getBoundingClientRect().top,只要这个值小于浏览器的高度 window.innerHeight 就说明进入可视区域,当图片进入可视区域时再去加载图片资源。

这种方法的缺点是,由于 scroll 事件密集发生,计算量很大,容易造成性能问题。

const element = document.getElementById("myElement");
const rect = element.getBoundingClientRect();

console.log(rect.top); // 元素顶部相对于视口的距离
console.log(rect.left); // 元素左侧相对于视口的距离
console.log(rect.width); // 元素的宽度
console.log(rect.height); // 元素的高度

IntersectionObserver

IntersectionObserver 是一个用于监听元素与视口交叉状态的 API(交叉观察器)。异步地观察一个或多个元素,当它们进入或离开视口时触发回调函数。

使用 IntersectionObserver,可以实现一些常见的交互效果,例如懒加载、无限滚动、可视化统计、网页广告的曝光量统计等。下面是一个简单的示例:

创建了一个 IntersectionObserver 实例,并通过 observe 方法观察了一个元素。当该元素进入或离开视口时,回调函数会被触发,并根据 isIntersecting 属性判断元素的可见状态。

// 指定根元素root、根元素的外边距rootMargin、执行callback的交叉比例的阀值threshold
const options = {
  root: null, // 观察器的根元素,必须是目标元素的父级元素; 默认:文档视口
  rootMargin: "0px", // 根元素的边界偏移量,类似于 CSS 中的 margin 属性。默认值是"0px 0px 0px 0px"
  threshold: 0.5, // 交叉比例阈值,当元素可见比例超过该阈值时触发回调函数
};

const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      console.log("Element is visible"); // 元素进入视口
    } else {
      console.log("Element is hidden"); // 元素离开视口
    }
  });
}, options);

const element = document.getElementById("myElement");
observer.observe(element);

定义观察到目标元素与根元素交叉区域变化时的回调函数 callback(entries, observer)。entries 数组中,每个成员都是一个 IntersectionObserverEntry 对象,如果同时有两个被观察的对象的可见性发生变化,entries 数组就会有两个成员。一般会触发两次 callback。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。

let callback = (entries, observer) => {
  entries.forEach((entry) => {
    consloe.log(entry); //包含目标元素的信息的对象
    // entry.time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
    // entry.target:被观察的目标元素,是一个 DOM 节点对象
    // entry.rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
    // entry.boundingClientRect:目标元素的矩形区域的信息
    // entry.intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
    // entry.intersectionRatio:根和目标元素的交叉区域的比例值,即intersectionRect占boundingClientRect的比例,0 为完全不可见,1 为完全可见
    // entry.isIntersecting:true表示从不可视状态变为可视状态。false表示从可视状态到不可视状态:false
  });
};

// observer.observe(targetNode);   指定目标元素 targetNode1、targetNode2,开始观察。
//observe的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。
observer.observe(targetNode1);
observer.observe(targetNode2); //开始观察目标元素。
// observer.disconnect(); //关闭观察器。
// observer.takeRecords(); //返回所有观察目标对象数组。
// observer.unobserve(targetNode1); //停止观察特定目标元素。
posted @ 2024-07-26 14:50  Echoyya、  阅读(86)  评论(0编辑  收藏  举报