0


前端神器IntersectionObserver,监听页面可视区域变化

在现代Web开发中,对页面中的元素进行视觉感知变得日益重要,尤其是在处理动态加载内容、无限滚动、广告跟踪和资源懒加载等功能时。传统的实现方式往往依赖于监听滚动事件,然后计算元素的位置判断是否进入可视区域,这种方法不仅代码复杂,而且会影响页面性能。

IntersectionObserver

API为此问题提供了一个高效且简便的解决方案。

什么是 IntersectionObserver?

IntersectionObserver

API允许你配置一个观察者来监视一个或多个元素与其祖先或顶级文档视口(

viewport

)的交叉状态。当被监视的元素进入或离开配置的视图区域时,会执行回调函数。这样,你就可以根据元素的可见性来执行相关操作,例如加载图片、播放视频、停止取数据等。

如何使用 IntersectionObserver?

示例代码:图片懒加载

假设我们有一个图像列表,希望当用户滚动到图片位置时才加载图片,以此来提高页面加载速度和性能。下面是如何使用

IntersectionObserver

来实现这一功能的示例代码:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Lazy Loading Images with IntersectionObserver</title><style>img{width: 100%;height: auto;margin-bottom: 20px;opacity: 0;transition: opacity 0.3s;}</style></head><body><divid="gallery"><!-- 假设图像列表非常长 --><imgdata-src="image1.jpg"alt="Lazy Image"><imgdata-src="image2.jpg"alt="Lazy Image"><imgdata-src="image3.jpg"alt="Lazy Image"><!-- 更多图片 --></div><script>
        document.addEventListener("DOMContentLoaded",function(){let observer;let images = document.querySelectorAll('img[data-src]');constloadImages=(image)=>{
                image.setAttribute('src', image.getAttribute('data-src'));
                image.onload=()=> image.style.opacity =1;
                observer.unobserve(image);};

            observer =newIntersectionObserver((entries, observer)=>{
                entries.forEach(entry=>{if(entry.isIntersecting){loadImages(entry.target);}});},{root:null,rootMargin:"50px 0px",threshold:0.01});

            images.forEach(image=>{
                observer.observe(image);});});</script></body></html>

我们设置了一个

IntersectionObserver

用来观察视图窗口,当图片元素进入视口时(加上50px的边界余量),会触发加载图片的函数。加载完毕后,会取消观察该元素,并逐渐显示图片。

灵活配置观察条件

IntersectionObserver API

提供了灵活的配置选项,让开发者能够根据具体的应用需求来调整元素的可见性检测。其中root、rootMargin和threshold是常用的配置项,下面将详细解释这些选项,并通过实例来说明它们的应用。

1.

root
root

属性指定了用作视口的元素,用于检查目标元素的可见性。如果没有指定或指定为

null

,则默认使用浏览器的视口(即

viewport

)。

示例: 假设我们有一个滚动容器

div

,我们想要观察这个容器内的元素是否可见,而不是整个页面的视口。此时,我们可以将这个

div

设置为

root

<divid="scrollContainer"style="height: 500px;overflow: auto;"><divid="targetElement">Watch me</div></div><script>const observer =newIntersectionObserver(callback,{root: document.getElementById('scrollContainer')});
observer.observe(document.getElementById('targetElement'));</script>

2.

rootMargin
rootMargin

属性是扩展或缩小

root

边界的边距,用来增加或减少

IntersectionObserver

的视口大小。这类似于CSS的

margin

属性,可以用像素(px)或百分比(%)来指定。

示例: 如果设置

rootMargin: "50px 0px"

, 这意味着观察区域将在顶部和底部各扩展50px。这对于提前触发事件(如懒加载图片)非常有用,可以在用户滚动到图片上方50px之前就开始加载图片。

<divid="targetElement">Watch me</div><script>const observer =newIntersectionObserver(callback,{root:null,// 使用默认视口rootMargin:"50px 0px"});
observer.observe(document.getElementById('targetElement'));</script>

3.

threshold
threshold

属性定义了目标元素与视口相交的比例(即交叉区域占目标元素的比例),在这个比例达到后触发回调。这个值可以是0到1之间的任何单个数字,或者一个数字数组。

示例: 如果设置

threshold: 0.1

, 那么只要目标元素有

10%

进入视口,回调函数就会被触发。这对于确保元素一进入视口就立即执行某些操作(如统计曝光)非常有用。

<divid="targetElement">Watch me</div><script>const observer =newIntersectionObserver(callback,{root:null,// 使用默认视口rootMargin:"0px",threshold:0.01});
observer.observe(document.getElementById('targetElement'));</script>

IntersectionObserver回调参数

let images = document.querySelectorAll('img[data-src]');constloadImages=(image)=>{};const observer =newIntersectionObserver((entries, observer)=>{
    entries.forEach(entry=>{if(entry.isIntersecting){loadImages(entry.target);}});},{});

images.forEach(image=>{
    observer.observe(image);});

在这段代码中,创建了一个新的

IntersectionObserver

实例,并为其设置了一个回调函数。当观察到的元素进入或离开交叉区域时,这个回调函数被触发。在回调内部,通过遍历

entries

数组,检查每个元素的

isIntersecting

属性。如果该属性为

true

,意味着元素已经进入视口,此时会调用

loadImages

函数加载图片。

1. entries

entries

是一个

IntersectionObserverEntry

对象的数组,表示所有被

IntersectionObserver

对象观察的元素的集合。每个

IntersectionObserverEntry

对象都包含关于某个特定目标元素和其相对于视口(或指定的

root

元素)的交叉状态信息。

每个

IntersectionObserverEntry

对象提供以下属性:

  • target:被观察的目标元素(DOM节点)。
  • isIntersecting:布尔值,表明目标元素是否与视口相交。
  • intersectionRatio:一个0到1之间的数字,描述了目标元素的可见部分占其总大小的比例。
  • intersectionRect:表示目标元素与视口交叉部分的矩形区域。
  • boundingClientRect:目标元素的边界框(bounding box)矩形,即元素的布局位置。
  • rootBounds:与root元素的边界框相对应的矩形,如果没有指定root,则是视口的边界框。

这些信息非常有用,特别是当你需要根据元素是否可见或其可见部分的比例来执行操作时(例如懒加载图像)。

2. observer

observer

参数是指向

IntersectionObserver

实例本身的引用。这允许你在回调函数中直接访问观察者实例,进行如取消观察、重新观察等操作。

通过这个引用,可以调用以下方法:

  • observe(target) :添加新的目标元素供IntersectionObserver观察。
  • unobserve(target) :停止观察一个目标元素。
  • disconnect() :停止观察所有目标元素,彻底关闭观察器。
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Intersection Observer Example</title></head><body><imgid="lazyImage"src="placeholder.jpg"data-src="actual-image.jpg"alt="Lazy Loaded Image"style="width: 100%;height: auto;"><script>
        document.addEventListener('DOMContentLoaded',function(){var img = document.getElementById('lazyImage');var observer =newIntersectionObserver(function(entries, observer){
                entries.forEach(entry=>{if(entry.isIntersecting){var img = entry.target;
                        img.src = img.getAttribute('data-src');
                        observer.unobserve(img);// Once loaded, stop observing}});},{rootMargin:'0px',threshold:0.1});

            observer.observe(img);});</script></body></html>

IntersectionObserver 的优势

  • 性能:使用IntersectionObserver可以避免在scroll事件中进行大量的DOM操作和计算,从而减少主线程的工作负载。
  • 准确性:直接由浏览器处理元素是否可见的计算,提高了可见性检测的准确性。
  • 易用性:API简单易用,大大简化了相关的编码工作。

总结

IntersectionObserver

为开发者提供了一个强大的工具,用于优化页面性能并改善用户体验。通过适当的使用这个API,可以在保证功能实现的同时,降低对性能的影响。不论是懒加载图片、实现无限滚动还是其他相关的动态内容展示,

IntersectionObserver

都是一个不可或缺的工具。

标签: 前端 算法

本文转载自: https://blog.csdn.net/qq_37834631/article/details/138840560
版权归原作者 SailingCoder 所有, 如有侵权,请联系我们删除。

“前端神器IntersectionObserver,监听页面可视区域变化”的评论:

还没有评论