js 监听元素是否出现在可视区域--IntersectionObserver

2024-02-23 10:20

本文主要是介绍js 监听元素是否出现在可视区域--IntersectionObserver,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

观察者模式监听判断dom元素是否在可视区域内
本项目是使用vue3的写法。

1.IntersectionObserver

IntersectionObserver可以用来自动监听元素是否进入了设备的可视区域之内,而不需要频繁的计算来做这个判断。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"

const observer = new IntersectionObserver(callback, option);

IntersectionObserver 是浏览器原生提供的构造函数,接受两个参数:

  • callback:可见性发现变化时的回调函数
  • option:配置对象(可选)。

构造函数的返回值是一个观察器实例。实例一共有4个方法:

  • observe:开始监听特定元素
  • unobserve:停止监听特定元素
  • disconnect:关闭监听工作
  • takeRecords:返回所有观察目标的对象数组

1.1 observe 方法

该方法需要接收一个target参数,值是Element类型,用来指定被监听的目标元素

// 获取元素
const target = document.getElementById("dom");// 开始观察
io.observe(target);

1.2 unobserve 方法

该方法需要接收一个target参数,值是Element类型,用来指定停止监听的目标元素

// 获取元素
const target = document.getElementById("dom");// 停止观察
io.unobserve(target);

1.3 disconnect 方法

该方法不需要接收参数,用来关闭观察器

// 关闭观察器
io.disconnect();
// 页面加载时监听元素
onMounted(() => {var demo3 = document.querySelector('document.querySelector(dom))  //  获取元素var observer = new IntersectionObserver((mutaions)=>{  // 创建IntersectionObserver对象console.log(mutaions[0].isIntersecting)})observer.observe(demo3)       // 需要监听的元素 
}       

1.4 takeRecords 方法

该方法不需要接收参数,返回所有被观察的对象,返回值是一个数组

// 获取被观察元素
const observerList = io.takeRecords();

1.5 callback 参数

目标元素的可见性变化时,就会调用观察器的回调函数callback。

callback一般会触发两次。一次是目标元素刚刚进入视口,另一次是完全离开视口。

const io = new IntersectionObserver((changes, observer) => {console.log(changes);console.log(observer);
});

1.6 options

  • threshold: 决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。用户可以自定义这个数组。比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。
  • root: 用于观察的根元素,默认是浏览器的视口,也可以指定具体元素,指定元素的时候用于观察的元素必须是指定元素的子元素
  • rootMargin: 用来扩大或者缩小视窗的的大小,使用css的定义方法,10px 10px 30px 20px表示top、right、bottom 和 left的值

2. IntersectionObserverEntry 对象

changes数组中的每一项都是一个IntersectionObserverEntry 对象

  • boundingClientRect:目标元素的矩形区域的信息
  • intersectionRatio:目标元素的可见比例,即intersectionRect占
    boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息
  • isIntersecting: 布尔值,目标元素与交集观察者的根节点是否相交(常用)
  • isVisible: 布尔值,目标元素是否可见(该属性还在试验阶段,不建议在生产环境中使用)
  • rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
  • target:被观察的目标元素,是一个 DOM 节点对象(常用)
  • time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒

3. 是否在可视区域

onMounted(() => {var observer = new IntersectionObserver((entries) => {console.log(111111, entries[0].isIntersecting);dataMap.showMyBox = !entries[0].isIntersecting; //返回true代表在页面可视区域,false代表不在页面可视区域。});observer.observe(document.querySelector(dom));
}
// 页面卸载时可解绑
onBeforeUnmount(() => {if (observer) {observer.unobserve(document.querySelector(dom)); //解绑元素observer.disconnect(); //停止监听}
});

4. 图片懒加载

使用 IntersectionObserver 非常容易实现图片懒加载,首先需要观察懒加载元素,然后等元素进入可视区域后设置图片 src;同时,还可以结合 IntersectionObserver.rootMargin 实现提前加载图片,一般可以设置为 1~2 倍浏览器窗口的视口高度,优化用户体验

/*** @method lazyLoad* @param {NodeList} $imgList      图片元素集合* @param {number}   preloadHeight 预加载高度*/
export function lazyLoad($imgList, preloadHeight = 1000) {const observer = new IntersectionObserver((entries) => {entries.forEach((entry) => {if (entry.isIntersecting) { // 目标元素出现在 root 可视区,返回 trueconst $target = entry.targetconst src = $target.getAttribute('lazyload')if (src) {$target.setAttribute('src', src) // 真正加载图片}observer.unobserve($target) // 解除观察}})}, {rootMargin: `0px 0px ${preloadHeight}px 0px`,})Array.prototype.forEach.call($imgList, ($item) => {if ($item.getAttribute('src')) return // 过滤已经加载过的图片observer.observe($item) // 开始观察})
}

使用方法:

// 图片元素设置 lazyload 属性
<img lazyload="图片链接" alt="图片说明">// 观察图片元素
lazyLoad(document.querySelectorAll("[lazyload]"))

5. 元素吸顶、吸底

如果页面结构比较简单可以直接使用 css 粘性布局。
IntersectionObserver 实现元素固定思路也很简单,首先需要给固定元素包一层父元素,父元素指定高度占位,防止固定元素吸附时页面抖动,然后观察父元素的可视状态变化,当父元素即将离开可视区域时改变固定元素的样式。

/*** @method fixBanner* @param {HTMLElement} $observeEle 观察元素* @param {HTMLElement} $fixEle     固定定位元素*/
export function fixBanner($observeEle, $fixEle) {const $ele = $fixEleconst observer = new IntersectionObserver((entries) => {entries.forEach((entry) => {if (entry.isIntersecting) {$ele.style.cssText = ''} else {$ele.style.cssText = 'position: fixed; top: 0; left: 0'}})}, {threshold: 1, // threshold 设置为 1 表示目标元素完全可见时触发回调函数})observer.observe($observeEle) // 开始观察
}

6. 加载更多

IntersectionObserver 实现加载更多需要在列表后面增加一个尾部元素(比如加载更多动画),当尾部元素进入可视区域就加载更多数据,注意尾部元素一定要一直处于所有列表元素的后面。

提前加载高度不能随意设置,如果设置太大会导致尾部元素一直处于可视状态。

function loadMore() {const observer = new IntersectionObserver((entries) => {const loadingEntry = entries[0]if (loadingEntry.isIntersecting) {// 请求数据并插入列表}},{rootMargin: '0px 0px 600px 0px', // 提前加载高度},)observer.observe(document.querySelector('.mod_loading')) // 观察尾部元素
}

这篇关于js 监听元素是否出现在可视区域--IntersectionObserver的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/738296

相关文章

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa

Flutter监听当前页面可见与隐藏状态的代码详解

《Flutter监听当前页面可见与隐藏状态的代码详解》文章介绍了如何在Flutter中使用路由观察者来监听应用进入前台或后台状态以及页面的显示和隐藏,并通过代码示例讲解的非常详细,需要的朋友可以参考下... flutter 可以监听 app 进入前台还是后台状态,也可以监听当http://www.cppcn