目录
IntersectionObserver 快速概述
桌面端
移动/平板
用例 1:懒加载图像
用例 2:元素离开视野时自动暂停视频
用例 3:查看已查看内容的多少
Article 2
感谢您的参与!
首页 web前端 css教程 交叉观察者的一些功能用途可以知道何时在元素中查看

交叉观察者的一些功能用途可以知道何时在元素中查看

Apr 21, 2025 am 11:19 AM

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/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555311750.jpg" class="lazy" alt="A Few Functional Uses for Intersection Observer to Know When an Element is in View "><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555481250.jpg" class="lazy" alt="A Few Functional Uses for Intersection Observer to Know When an Element is in View "><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174520555431263.jpg" 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中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

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

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

VUE 3 VUE 3 Apr 02, 2025 pm 06:32 PM

它的出局!恭喜Vue团队完成了完成,我知道这是一项巨大的努力,而且很长时间。所有新文档也是如此。

使用Redwood.js和Fauna构建以太坊应用 使用Redwood.js和Fauna构建以太坊应用 Mar 28, 2025 am 09:18 AM

随着最近比特币价格超过20k美元的攀升,最近打破了3万美元,我认为值得深入研究创建以太坊

您可以从浏览器获得有效的CSS属性值吗? 您可以从浏览器获得有效的CSS属性值吗? Apr 02, 2025 pm 06:17 PM

我有人写了这个非常合法的问题。 Lea只是在博客上介绍了如何从浏览器中获得有效的CSS属性。那样的是这样。

带有粘性定位的堆叠卡和一点点的杂物 带有粘性定位的堆叠卡和一点点的杂物 Apr 03, 2025 am 10:30 AM

前几天,我发现了科里·金尼文(Corey Ginnivan)网站上的这一点,当您滚动时,彼此之间的卡片堆放集。

在CI/CD上有点 在CI/CD上有点 Apr 02, 2025 pm 06:21 PM

我说的“网站”比“移动应用程序”更合适,但我喜欢Max Lynch的框架:

在WordPress块编辑器中使用Markdown和本地化 在WordPress块编辑器中使用Markdown和本地化 Apr 02, 2025 am 04:27 AM

如果我们需要直接在WordPress编辑器中向用户显示文档,那么最佳方法是什么?

比较浏览器的响应式设计 比较浏览器的响应式设计 Apr 02, 2025 pm 06:25 PM

这些桌面应用程序中有许多目标是同时在不同的维度上显示您的网站。因此,例如,您可以写作

为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? 为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? Apr 05, 2025 pm 05:51 PM

关于Flex布局中紫色斜线区域的疑问在使用Flex布局时,你可能会遇到一些令人困惑的现象,比如在开发者工具(d...

See all articles