深入浅出详解Intersection Observer交叉观察器 API

原文地址:原文连接

一、前言

过去,要检测一个元素是否可见或者两个元素是否相交并不容易,很多解决办法不可靠或性能很差。然而,随着互联网的发展,这种需求却与日俱增,比如,下面这些情况都需要用到相交检测:
在页面滚动时“懒加载”图像或其他内容。
实现“无限滚动”网站,在滚动过程中加载和显示越来越多的内容,这样用户就不必翻页了。
报告广告的可见度,以便计算广告收入。
根据用户是否能看到结果来决定是否执行任务或动画进程。
视频的播放和暂停。

过去实施相交检测时,需要调用事件处理程序和循环方法,如 Element.getBoundingClientRect() 来为每个受影响的元素建立所需的信息。由于所有这些代码都在主线程上运行,因此即使是其中的一行代码也会导致性能问题。当网站加载这些程序时,情况会变得非常糟糕,体验非常不好。

直到 Intersection Observer API 的出现!

Intersection Observer API(交叉观察器API)是一种JavaScript的API,它提供了一种异步观察目标元素与祖先元素(或顶级文档的视口)交叉状态变化的方法。这个API主要用于高效解决在网页开发中需要频繁判断元素是否进入“视口”(viewport)的问题,比如实现懒加载、无限滚动、可视化统计、视频播放等交互效果,同时减少性能开销,提升用户体验。

二、基本用法

交叉观察器 API 允许你配置一个回调函数,当以下情况发生时会被调用:

目标元素与设备视口或指定元素相交。在交叉观察器 API 中,指定元素被称为根元素或根。

观察器(Observer)第一次监听观察目标元素。

通常情况下,需要观察目标元素最近的可滚动祖先的交集变化,如果目标元素不是可滚动元素的后代,则需要观察设备视口的交集变化。要观察相对于设备视口的交集,请为 root 选项指定 null。无论你是使用视口还是其他元素作为根元素,API 的工作方式都是一样的,只要目标元素的可见性发生变化,与根元素的交集达到所需的程度,就会执行你提供的回调函数。

目标元素与其根元素的交集程度就是交叉比。它表示目标元素可见的百分比,数值介于 0.0 和 1.0 之间。

2.1 创建交叉观察器
通过调用 IntersectionObserver 构造函数,创建交叉观测器,并将回调函数传给它,当一个方向或另一个方向越过阈值时,就运行该函数。

let options = {root: document.querySelector("#scrollArea"),rootMargin: "0px",threshold: 1.0,
};let observer = new IntersectionObserver(callback, options);

传递到 IntersectionObserver() 构造函数的 options 对象,可以控制在什么情况下调用观察器的回调。它有以下字段:

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 意味着在每个像素都可见之前,阈值不会被认为已通过。

2.2 回调函数
回调函数在交叉状态变化时执行,接收两个参数:一个entries数组和一个observer对象。entries数组中的每个元素都是一个IntersectionObserverEntry对象,表示目标元素与根元素的交叉状态信息。

const callback = (entries, observer) => {  entries.forEach(entry => {  if (entry.isIntersecting) {  // 元素进入视口  doSomething()} else {  // 元素离开视口  doSomething() }  });  
};

以图片懒加载为例(见下文):

图片元素进入视口entries的信息:
图片元素进入视口entries的信息
图片元素未进入或离开视口entries的信息:
在这里插入图片描述

observer打印信息:在这里插入图片描述

2.3 观察目标元素

const ob = new IntersectionObserver();
ob.observe(targetElement);

使用observe方法将目标元素添加到观察器的观察列表中,targetElement代表需要被观察的目标元素。

2.4 停止观察
如果需要停止观察某个目标元素,可以使用unobserve方法。

const ob = new IntersectionObserver();
ob.unobserve(targetElement);

2.5 终止所有观察
disconnect()方法终止对所有目标元素可见性变化的观察。

const ob = new IntersectionObserver();
ob.disconnect();

2.6 IntersectionObserverEntry对象

  • boundingClientRect:目标元素的矩形区域的信息。

  • intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例。

  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息。

  • rootBounds:根元素的矩形区域的信息。

  • isIntersecting:目标元素是否与视口(或根元素)交叉。

  • target:被观察的目标元素。

  • time:可见性发生变化的时间戳。

三、实现图片懒加载功能

<div class="container"><div class="img-item"><img src="./img/default.png" alt="" data-src="./girl/img-1.jpeg" /></div><div class="img-item"><img src="./img/default.png" alt="" data-src="./girl/img-2.jpeg" /></div><div class="img-item"><img src="./img/default.png" alt="" data-src="./girl/img-3.jpeg" /></div>//还有好多张的......
</div>
.container {width: 900px;margin: 0 auto;
}
.container .img-item {display: inline-block;width: 17%;height: 200px;margin: 10px 1%;
}
.container .img-item img {width: 100%;height: 100%;
}

data-src 属性是真实图片的URL,而 img 标签的 src 属性是默认图片占位符。

const options = {root: null,// rootMargin: '0px',threshold: 0.5
}
// 创建观察器
const ob = new IntersectionObserver((entries, observer) => {// 循环每个元素观察其状态for (const entry of entries) {// 元素进入视口if(entry.isIntersecting) {const img = entry.target;// 把data-src的值赋值给srcimg.src = img.dataset.src;// 已经给src赋过值的,停止观察改元素ob.unobserve(img);}}
}, options);// 获取所有懒加载元素
const imgs = document.querySelectorAll('img[data-src]');
// 循环给每个懒加载元素添加观察器
imgs.forEach(item => {ob.observe(item);
})

在这里插入图片描述

四、实现滚动加载更多

创建观察器,获取页面下方加载更多的loading元素,并给该元素添加到观察器中,当观察到下面加载更多的loading元素进入视口,调用loadMoreImages方法加载更多图片。

// 调用接口请求图片
let imgList = [];
async function loadMoreImages(size = 10) {// 加入返回的结果为res.dataimgList = [...imgList, ...res.data];isLoading = false;
}
loadMoreImages(10)//创建观察器
const ob = new IntersectionObserver((entries) => {// 当获取加载更多的loading元素进入视口,调用loadMoreImages方法const entry = entries[0];if(entry.isIntersecting) {loadMoreImages(10)}
}, {threshold: 0
})// 获取加载更多的loading元素
const spin = document.querySelector('.spin');
ob.observe()

五、实现视频自动播放

经常刷某日头条、某瓜视频等网页时,留心观察会发现,当视频完全进入视口或部分进入视口时视频自动播放,当视频离开视口部分时会停止播放。使用Intersection Observer API实现这个效果就相当容易了。

<!DOCTYPE html>
<html><head><style>video {width: 100%;height: 500px;margin-bottom: 20px;}</style></head><body><video controls loop><source src="./video/video-1.mov" type="video/mp4"></video><video controls loop><source src="./video/video-4.mov" type="video/mp4"></video><video controls loop><source src="./video/video-3.mov" type="video/mp4"></video></body><script type="text/javascript">const videos = document.querySelectorAll('video');//创建观察器const ob = new IntersectionObserver((entries) => {for (const entry of entries) {// 视频完整进入视口开始播放,完全离开视口停止播放const video = entry.target;if (entry.isIntersecting) {video.play();} else {video.pause();}}}, {threshold: 1})videos.forEach(vdo => {ob.observe(vdo);})</script>
</html>

在这里插入图片描述

小结

在这里插入图片描述
Intersection Observer API是异步的,不随着目标元素的滚动同步触发。

注册的回调函数将在主线程中执行,因此执行速度应尽可能快,避免耗时操作。

兼容性:虽然大部分现代浏览器都支持Intersection Observer API,但在使用时仍需考虑兼容性问题。

当目标元素或其祖先元素使用了一些特殊的定位属性(如fixed、sticky或transform),或者元素本身被部分遮挡时,Intersection Observer API可能会产生不准确的观察结果,尽量避免在目标元素或其祖先元素上使用这些可能导致定位问题的属性。

综上所述,Intersection Observer API是一种强大的工具,用于优化网页的性能和用户体验。通过合理使用这个API,开发者可以更加高效地管理元素的可见性,实现各种交互效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1549937.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

联想电脑怎么开启vt_联想电脑开启vt虚拟化教程(附intel和amd主板开启方法)

最近使用联想电脑的小伙伴们问我&#xff0c;联想电脑怎么开启vt虚拟。大多数可以在Bios中开启vt虚拟化技术&#xff0c;当CPU支持VT-x虚拟化技术&#xff0c;有些电脑会自动开启VT-x虚拟化技术功能。而大部分的电脑则需要在Bios Setup界面中&#xff0c;手动进行设置&#xff…

QT九月28日

1.实现登录界面 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget>class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget(); }; #endif // WIDGET_H源文件 #include "widget.h" #include <QIcon> #in…

订餐点餐|订餐系统基于java的订餐点餐系统小程序设计与实现(源码+数据库+文档)

订餐点餐系统小程序 目录 基于java的订餐点餐系统小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布…

快递单号物流跟踪管理快速筛选出已签收单号

看着满屏的单号&#xff0c;是不是感觉眼前一黑要查询到什么时候&#xff1f;别灰心&#xff0c;这不快递批量查询高手来了&#xff01;这神器就是用来查询物流的好帮手。一键筛选已签收件单号&#xff0c;并导出表格。有了它&#xff0c;你也能轻松查询大量的单号物流。一起试…

生信初学者教程(十五):差异结果的热图

文章目录 介绍加载R包导入数据画图函数热图输出结果总结介绍 热图是一种数据可视化工具,用于展示矩阵数据中的数值大小,通过颜色的深浅或色调变化来表示不同的数值。通常用于生物信息学、统计学和数据分析等领域,以便直观地比较和分析大量数据。 热图展示的是一个二维的数据…

图神经网络实战——分层自注意力网络

图神经网络实战——分层自注意力网络 0. 前言1. 分层自注意力网络1.1 模型架构1.2 节点级注意力1.3 语义级注意力1.4 预测模块 2. 构建分层自注意力网络相关链接 0. 前言 在异构图数据集上&#xff0c;异构图注意力网络的测试准确率为 78.39%&#xff0c;比之同构版本有了较大…

信息安全工程师(26)物理安全概念与要求

前言 物理安全是网络安全体系中的重要组成部分&#xff0c;它关注于保护物理环境、设备和资源免受未经授权的访问、破坏、损坏或盗窃。 一、物理安全概念 物理安全&#xff0c;也称为实体安全&#xff0c;是指通过采取各种物理措施来保护支持网络信息系统运行的硬件&#xff08…

你还在用Java8吗?

Java 11 在企业中&#xff0c;Java的不同版本使用情况随着时间在不断变化。根据最新的数据报告&#xff0c;以下是一些关键点&#xff1a; Java 11 和 Java 17 成为企业中最常用的长期支持&#xff08;LTS&#xff09;版本&#xff0c;使用率分别为 48% 和 45%&#xff0c;而 …

1Panel安装部署证书(httpsok.com)

1Panel安装部署证书(httpsok.com) 购买服务器 推荐购买香港服务器&#xff0c;这样通过域名访问就不需要备案。 创建静态站点 申请SSL证书 进入 httpsok.com&#xff0c;点击申请证书 输入站点域名 根据提示&#xff0c;添加DNS解析记录 添加成功后&#xff0c;提示域名验证…

免费送源码:Javaspringboot++MySQL springboot 社区互助服务管理系统小程序 计算机毕业设计原创定制

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受居民的喜爱&#xff0c;社区互助服务管理系统小程序被居民普遍使用&#xff0c;为…

【二叉平衡搜索树】Treap

前置 本篇是平衡树-treap的补充学习笔记。 Treap - 树堆 学习基础&#xff1a;适合一定基础的&#xff1a;比如&#xff0c;实现了经典二叉搜索树&#xff08;常用的几个函数写过&#xff09;&#xff0c; 和二叉堆&#xff08;数组的上浮下沉会写吗&#xff1f;&#xff09;&a…

Win11右键默认显示更多设置教程

Win11最大的变化之一莫过于右键菜单发生了变化&#xff0c;最大的问题是什么&#xff0c;是右键菜单很多时候需要点两次&#xff0c;实在是反人类&#xff0c;太麻烦了。 简直是反人类&#xff01; 必须使用“显示更多选项”的右键菜单。 以管理员方式运行CMD 复制以下命令直…

IP6537_C_30W20V--移动设备快充的得力助手,集成 14 种快充协议的降压 SoC

IP6537_C_30W20V是一款集成同步开关的降压转换器、支 持 14 种输出快充协议、支持 Type-C 输出和 USB PD2.0/PD3.0(PPS)协议的 SoC&#xff0c;为车载充电器、 快充适配器、智能排插提供完整的解决方案。 IP6537_C_30W20V支持 USB Type-C 或者 USB A 输出&#xff0c; 5V 输出功…

C++的STL标准模板库容器--vector类

前言&#xff1a;vector类也可以叫作顺序表&#xff0c;他同样也在STL库中的容器模块中&#xff0c;我还是主要讲常用的几个成员函数和成员变量&#xff0c;同时它晚于string类&#xff0c;所以在设计上没有string冗余。 vector类是一个和数组类似的容器&#xff0c;它属于随机…

插上网线无法连接网络,控制面板以太网消失 | 如何重装网络驱动

如果你确定你的网线没问题&#xff0c;网线插口没问题&#xff0c;那你大概率就是驱动问题&#xff0c;可以试一下本方法。 0 以太网消失 事情是这样的&#xff0c;我工作时候需要接内网&#xff0c;插网线&#xff0c;摸鱼时候连外网&#xff0c;我就把网线关了。 每次插网线…

【Python大语言模型系列】开源机器人对话系统框架RASA介绍与使用(案例分析)

这是我的第361篇原创文章。 一、引言 Rasa是一个开源的对话式 AI 框架&#xff0c;用于构建自定义的对话式 AI 助手。它可以处理自然语言理解&#xff08;NLU&#xff09;和对话管理&#xff08;DM&#xff09;&#xff0c;使得开发者能够轻松地创建功能丰富的对话式 AI 应用。…

番外篇 | 应对遮挡挑战,北航提出新型模型YOLOv5-FFM表现优异

前言:Hello大家好,我是小哥谈。在本文中,作者提出了一种改进的轻量级YOLOv5-FFM模型来解决行人检测遮挡问题。为了实现目标,作者在YOLOv5模型框架基础上进行了改进,并引入了Ghost模块和SE模块。此外,作者还设计了一个局部特征融合模块(FFM)来处理行人检测中的遮挡问题。…

I/O中断处理过程

中断控制器位于CPU和外设之间&#xff0c;用于处理I/O中断请求。以下是一个简化的中断控制器&#xff1a; 现在有A,B,C三个中断源。中断响应优先级&#xff1a;A>B>C&#xff0c;中断处理优先级&#xff1a;C>B>A 假设CPU正在处理A中断源的中断请求&#xff0c;此时…

Mixture-of-Experts (MoE): 条件计算的诞生与崛起【上篇】

大型语言模型&#xff08;LLM&#xff09;的现代进步主要是缩放定律的产物[6]。 假设模型是在足够大的数据集上训练出来的&#xff0c;那么随着底层模型规模的增加&#xff0c;我们会看到性能的平滑提升。 这种扩展规律最终促使我们创建了 GPT-3 以及随后的其他&#xff08;更强…

Excel技巧:Excel批量提取文件名

Excel是大家经常用来制作表格的文件&#xff0c;比如输入文件名&#xff0c;如果有大量文件需要输入&#xff0c;用张贴复制或者手动输入的方式还是很费时间的&#xff0c;今天和大家分享如何批量提取文件名。 打开需要提取文件名的文件夹&#xff0c;选中所有文件&#xff0c…