Intersection Observer API:实时监控元素是否可见
你可能不知道,JavaScript 近年来悄然积累了许多观察者,而 Intersection Observer 正是其中一种强大的工具。观察者是实时监控特定事件的对象,就像观鸟者坐在他们最喜欢的地方等待鸟儿出现一样。不同的观察者观察不同的目标。
我最早接触到的观察者是 Mutation Observer,它用于检测 DOM 树的更改。当时它是独一无二的,但现在我们有了更多观察者。
Intersection Observer 观察元素与其祖先元素或页面可见区域(即视口)之间的“交叉”(即元素进入或离开视口)。这有点像观看火车经过车站。你可以看到火车何时进站、何时离站以及它停站了多久。
了解元素何时即将进入视野、何时消失或自进入视野以来已过去多长时间,都具有非常实用的应用。因此,我们将了解一些用例——在通过 Intersection Observer API 创建 IntersectionObserver 对象的代码之后。
IntersectionObserver 快速概述
在撰写本文时,Intersection Observer API 已经获得了广泛的支持。
浏览器支持数据来自 Caniuse,其中包含更多详细信息。数字表示浏览器在该版本及更高版本中支持该功能。
桌面端
移动/平板
但是,如果你想在使用 Intersection Observer 时检查它是否受支持,你可以查看 window 对象中是否存在 IntersectionObserver 属性:
if(!!window.IntersectionObserver){} /* or */ if('IntersectionObserver' in window){}
好的,现在来看一下对象的创建:
var observer = new IntersectionObserver(callback, options);
IntersectionObserver 对象的构造函数接受两个参数。第一个是回调函数,当观察者注意到交叉并异步传递有关该交叉的一些数据时,该函数将被执行。
第二个(可选)参数是options,一个包含信息的对象,用于定义什么是“交叉”。我们可能不想知道元素何时即将进入视野,而只想在它完全可见时才知道。诸如此类的事情是通过 options 参数定义的。
Options 有三个属性:
- root – 被观察元素将与其交叉的祖先元素/视口。把它想象成火车将与其交叉的车站。
- rootMargin – 根元素的周长,缩小或扩大根元素的观察区域以检测交叉。它类似于 CSS margin 属性。
- threshold – 值(介于 0 和 1.0 之间)的数组,每个值代表元素与根交叉或越过根的距离,在此距离下将触发回调。
假设我们的 threshold 为 0.5。当元素进入或超过其半可见阈值时,将触发回调。如果值为[0.3, 0.6]
,则当元素进入或超过其 30% 可见阈值以及其 60% 可见阈值时,将触发回调。
现在理论就讲到这里。让我们看一些演示。首先是懒加载。
用例 1:懒加载图像
要查看加载标记
,请查看此网页,因为嵌入式演示不会显示该标记。
CSS-Tricks 之前已经彻底介绍了懒加载,通常是这样完成的:显示一个轻量级占位符,图像将显示在该占位符的位置,然后在图像进入(或即将进入)视野时将其替换为预期的图像。相信我,实现这一点一点也不懒惰——也就是说,直到我们得到一些原生代码来使用。
我们将应用相同的机制。首先,我们有一堆图像,并定义了一个初始显示的占位符图像。我们使用一个数据属性来携带要显示的原始图像的 URL,该属性定义了实际图像在进入视野时要加载的图像。
<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555311750.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="A Few Functional Uses for Intersection Observer to Know When an Element is in View "><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555481250.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="A Few Functional Uses for Intersection Observer to Know When an Element is in View "><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555431263.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="A Few Functional Uses for Intersection Observer to Know When an Element is in View ">
其余的是脚本。
let observer = new IntersectionObserver( (entries, observer) => { entries.forEach(entry => { /* 在这里处理每个交叉*/ }); }, {rootMargin: "0px 0px -200px 0px"});
上面的回调函数是一个箭头函数(尽管你可以使用普通函数)。
回调函数接收两个参数:一组entries,包含有关每个交叉的信息;以及observer本身。可以过滤或循环遍历这些 entries,然后处理我们想要的交叉 entries。至于 options,我只提供了 rootMargin 值,让 root 和 threshold 属性采用其默认值。
root 的默认值为视口,threshold 的默认值为 0——这大致可以解释为“元素出现在视口的那一刻就通知我!”
然而,奇怪的是,我使用 rootMargin 将视口的观察区域底部减少了 200 像素。我们通常不会在懒加载中这样做。相反,我们可能会增加边距或让它保持默认值。但是,在这种情况下,我们通常不会减少边距。我这样做只是因为我想演示在观察区域的阈值处加载的原始图像。否则,所有操作都将在视野外发生。
当图像与视口的观察区域(在演示中距离底部上方 200 像素)相交时,我们将占位符图像替换为实际图像。
let observer = new IntersectionObserver( (entries, observer) => { entries.forEach(entry => { /* 占位符替换 */ entry.target.src = entry.target.dataset.src; observer.unobserve(entry.target); }); }, {rootMargin: "0px 0px -200px 0px"});
entry.target
是被观察者观察的元素。在我们的例子中,这些是图像元素。一旦在图像元素中替换了占位符,我们就无需再观察它了,因此我们对其调用观察者的 unobserve
方法。
现在观察者已准备就绪,是时候使用其 observe
方法开始观察所有图像了:
document.querySelectorAll('img').forEach(img => { observer.observe(img) });
就是这样!我们已经懒加载了图像。进入下一个演示。
用例 2:元素离开视野时自动暂停视频
假设我们在 YouTube 上观看视频,并且(无论出于何种原因)我们想要向下滚动以阅读评论。我不知道你怎么样,但我通常不会在这样做之前先暂停视频,这意味着我在浏览时会错过一些视频。
如果当我们从视频滚动离开时视频会自动暂停,那不是很好吗?如果视频在重新进入视野时恢复播放,那就更好了,这样就无需点击播放或暂停按钮了。
Intersection Observer 当然可以做到这一点。
这是我们在 HTML 中的视频:
<video controls="" src="OSRO-animation.mp4"></video>
这是我们在每次交叉(即 entry)期间暂停和播放视频的方式:
let video = document.querySelector('video'); let isPaused = false; /* 自动暂停视频的标志 */ let observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if(entry.intersectionRatio!=1 && !video.paused){ video.pause(); isPaused = true; } else if(isPaused) {video.play(); isPaused=false} }); }, {threshold: 1}); observer.observe(video);
在我向你展示如何在每次交叉(即 entry)期间暂停和播放视频之前,我想提请你注意 options 的 threshold 属性。
threshold 的值为 1。root 和 rootMargin 将采用默认值。这等同于说:“嘿,一旦元素在视口中完全可见,就通知我。”
一旦发生交叉并触发回调,我们将根据以下逻辑暂停或播放视频:
我没有为视频调用 unobserve
,因此观察者会一直观察视频,并在每次视频离开视野时暂停。
用例 3:查看已查看内容的多少
这可以根据你的内容和你首选的衡量已查看内容多少的方式以多种方式解释和实现。
对于一个简单的示例,我们将观察页面上文章列表中每篇文章的最后一段。一旦文章的最后一段完全可见,我们将认为该文章已阅读——就像我们可能会说看到火车的最后一节车厢就等于看到了整列火车一样。
这是一个演示,它显示页面上的两篇文章,每篇文章包含多段文字。
我们简化的 HTML 如下所示:
<div></div> <h2 id="Article">Article 1</h2> <p></p> <h2 id="Article">Article 2</h2> <p></p>
let n=0; /* 已查看的文章总数 */ let count = document.querySelector('#count'); let observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if(entry.isIntersecting){ count.textContent= `articles fully viewed - ${ n}`; observer.unobserve(entry.target); } }); }, {threshold: 1}); document.querySelectorAll('article > p:last-child').forEach(p => { observer.observe(p) });
在每次交叉(即文章的最后一段完全可见)期间,我们都会递增一个计数器:n,它表示已阅读的文章总数。然后,我们在文章列表上方显示该数字。
一旦我们计算了最后一段的交叉,就不需要再观察它了,因此我们对其调用 unobserve
。
感谢您的参与!
这就是我们将一起查看的本篇文章中的示例。你可能已经了解了如何使用它来观察元素并根据它们与视口的交叉位置触发事件。
也就是说,在根据通过观察者获得的交叉数据进行视觉更改时,需要谨慎。当然,在记录交叉数据时,Intersection Observer 非常方便。但是,当它用于进行屏幕上的更改时,我们需要确保更改不会滞后,这是一种可能性,因为我们基本上是根据异步检索的数据进行更改。这可能需要一些时间来加载。
正如我们所看到的,每个交叉 entry 都有一个属性集,用于传达有关交叉的信息。在本篇文章中,我没有介绍所有这些属性,因此请务必查看它们。
The image is preserved in its original format. Note that the tables are empty in the input and thus remain empty in the output. I have also made stylistic changes to improve readability and flow, while maintaining the original meaning.
以上是交叉观察者的一些功能用途可以知道何时在元素中查看的详细内容。更多信息请关注PHP中文网其他相关文章!

SVG具有自己的一套元素,属性和属性集,以至于内联SVG代码可能会变得漫长而复杂。通过利用CSS和SVG 2规范的一些即将到来的功能,我们可以减少该代码以进行清洁标记。

PWA(Progressive Web应用程序)已经与我们在一起了一段时间。但是,每次我尝试向客户解释它时,同样的问题都会出现:“我的用户会成为


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

Dreamweaver Mac版
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

WebStorm Mac版
好用的JavaScript开发工具