IntersectionObserver对象

IntersectionObserver对象,从属于Intersection Observer API,提供了一种异步观察目标元素与其祖先元素或顶级文档视窗viewport交叉状态的方法,祖先元素与视窗viewport被称为根root,也就是说IntersectionObserver API,可以自动观察元素是否可见,由于可见visible的本质是,目标元素与视口产生一个交叉区,所以这个API叫做交叉观察器,兼容性https://caniuse.com/?search=IntersectionObserver

描述

IntersectionObserver解决了一个长期以来Web的问题,观察元素是否可见,这个可见visible的本质是,目标元素与视口产生一个交叉区,所以这个API叫做交叉观察器。
要检测一个元素是否可见或者两个元素是否相交并不容易,很多解决办法不可靠或性能很差。现在很多需求下都需要用到相交检测,例如图片懒加载、内容无限滚动、检测元素的曝光情况、可视区域播放动画等等,相交检测通常要用到onscroll事件监听,并且可能需要频繁调用Element.getBoundingClientRect()等方法以获取相关元素的边界信息,事件监听和调用Element.getBoundingClientRect都是在主线程上运行,因此频繁触发、调用可能会造成性能问题,这种检测方法极其怪异且不优雅。
Intersection Observer API会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时或viewport,或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行,这样网站的主线程不需要再为了监听元素相交而辛苦劳作,浏览器会自行优化元素相交管理,注意Intersection Observer API无法提供重叠的像素个数或者具体哪个像素重叠,他的更常见的使用方式是当两个元素相交比例在N%左右时,触发回调,以执行某些逻辑。

const io = new IntersectionObserver(callback, option);// 开始观察
io.observe(document.getElementById("example"));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
  • 参数callback,创建一个新的IntersectionObserver对象后,当其监听到目标元素的可见部分穿过了一个或多个阈thresholds时,会执行指定的回调函数。
  • 参数optionIntersectionObserver构造函数的第二个参数是一个配置对象,其可以设置以下属性:
    • threshold属性决定了什么时候触发回调函数,它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例intersectionRatio达到0时触发回调函数,用户可以自定义这个数组,比如[0, 0.25, 0.5, 0.75, 1]就表示当目标元素0%25%50%75%100%可见时,会触发回调函数。
    • root属性指定了目标元素所在的容器节点即根元素,目标元素不仅会随着窗口滚动,还会在容器里面滚动,比如在iframe窗口里滚动,这样就需要设置root属性,注意,容器元素必须是目标元素的祖先节点。
    • rootMargin属性定义根元素的margin,用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小,它使用CSS的定义方法,比如10px 20px 30px 40px,表示toprightbottomleft四个方向的值。
  • 属性IntersectionObserver.root只读,所监听对象的具体祖先元素element,如果未传入值或值为null,则默认使用顶级文档的视窗。
  • 属性IntersectionObserver.rootMargin只读,计算交叉时添加到根root边界盒bounding box的矩形偏移量,可以有效的缩小或扩大根的判定范围从而满足计算需要,此属性返回的值可能与调用构造函数时指定的值不同,因此可能需要更改该值,以匹配内部要求,所有的偏移量均可用像素pixelpx或百分比percentage%来表达,默认值为0px 0px 0px 0px
  • 属性IntersectionObserver.thresholds只读,一个包含阈值的列表,按升序排列,列表中的每个阈值都是监听对象的交叉区域与边界区域的比率,当监听对象的任何阈值被越过时,都会生成一个通知Notification,如果构造器未传入值,则默认值为0
  • 方法IntersectionObserver.disconnect(),使IntersectionObserver对象停止监听工作。
  • 方法IntersectionObserver.observe(),使IntersectionObserver开始监听一个目标元素。
  • 方法IntersectionObserver.takeRecords(),返回所有观察目标的IntersectionObserverEntry对象数组。
  • 方法IntersectionObserver.unobserve(),使IntersectionObserver停止监听特定目标元素。

此外当执行callback函数时,会传递一个IntersectionObserverEntry对象参数,其提供的信息如下。

  • time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒。
  • target:被观察的目标元素,是一个DOM节点对象。
  • rootBounds:根元素的矩形区域的信息,是getBoundingClientRect方法的返回值,如果没有根元素即直接相对于视口滚动,则返回null
  • boundingClientRect:目标元素的矩形区域的信息。
  • intersectionRect:目标元素与视口或根元素的交叉区域的信息。
  • intersectionRatio:目标元素的可见比例,即intersectionRectboundingClientRect的比例,完全可见时为1,完全不可见时小于等于0

应用

实现一个使用IntersectionObserver的简单示例,两个方块分别可以演示方块1是否在屏幕可见区域内以及方块2是否在方块1的相对可见交叉区域内,另外可以使用IntersectionObserver可以进行首屏渲染的优化,可以参考https://github.com/WindrunnerMax/EveryDay/blob/master/Vue/Vue%E9%A6%96%E5%B1%8F%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E7%BB%84%E4%BB%B6.md

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>body{margin: 0;padding: 0;height: 100vh;width: 100vw;overflow-x: hidden;}.flex{display: flex;}.top-fixed{top: 0;position: fixed;}.placeholder1{width: 100%;}#box1{height: 200px; overflow-y: auto; border: 1px solid #aaa; width: 60%;}.box1-placeholder{height: 105vh;}#box2{height: 100px; background-color: blue; margin-top: 300px; width: 60%;}.box2-placeholder{height: 205px;}</style>
</head>
<body><section class="flex top-fixed"><div class="flex">BOX1:</div><div class="flex" id="box1-status">invisible</div><div class="flex">&nbsp;BOX2:</div><div class="flex" id="box2-status">invisible</div></section><div class="box1-placeholder"></div><div id="box1"><div class="box2-placeholder"></div><div id="box2"></div>   <div class="box2-placeholder"></div></div><div class="box1-placeholder"></div></body>
<script>(function(){const box1 = document.querySelector("#box1");const box2 = document.querySelector("#box2");const box1Status = document.querySelector("#box1-status");const box2Status = document.querySelector("#box2-status");const box1Observer = new IntersectionObserver(entries => {entries.forEach(item => {// `intersectionRatio`为目标元素的可见比例,大于`0`代表可见if (item.intersectionRatio > 0) {box1Status.innerText = "visible";}else{box1Status.innerText = "invisible";}});}, {root: document});const box2Observer = new IntersectionObserver(entries => {entries.forEach(item => {// `intersectionRatio`为目标元素的可见比例,大于`0`代表可见if (item.intersectionRatio > 0) {box2Status.innerText = "visible";}else{box2Status.innerText = "invisible";}});}, {root: box1});box1Observer.observe(box1);box2Observer.observe(box2);})();</script>
</html>

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://www.jianshu.com/p/eadd83d794c8
https://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html
https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver

IntersectionObserver对象相关推荐

  1. Html图片懒加载动画,Intersection Observer实现滚动到相应区域执行动画及图片懒加载...

    Intersection observer API提供了一种方法,可以异步观察目标元素与祖先元素或相对于浏览器视口(root)的交集变化. 很多种情况下都需要用到元素交集变化的信息,例如:当页面滚动时 ...

  2. Vue首屏性能优化组件

    Vue首屏性能优化组件 简单实现一个Vue首屏性能优化组件,现代化浏览器提供了很多新接口,在不考虑IE兼容性的情况下,这些接口可以很大程度上减少编写代码的工作量以及做一些性能优化方面的事情,当然为了考 ...

  3. Uni-app API

    Uni-app的各种api,各种功能还是很全面的,而且基于vue用法,本身也带有自己的一套UI系统,代码也能兼容app和小程序,还是挺方便的. 基础 #日志打印 日志打印       向控制台打印日志 ...

  4. [译] 2019 前端性能优化年度总结 — 第五部分

    原文地址:Front-End Performance Checklist 2019 - 5 原文作者:Vitaly Friedman 译文出自:掘金翻译计划 本文永久链接:github.com/xit ...

  5. (译)2019年前端性能优化清单 — 中篇

    (译)2019年前端性能优化清单 - 上篇 (译)2019年前端性能优化清单 - 中篇 (译)2019年前端性能优化清单 - 下篇 目录 资源优化 17. 使用 Brotli 或 Zopfli 进行纯 ...

  6. 前端面试题【131道】

    前端面试题 1.vue2和vue3的主要区别 3.Apply/call/bind的原理是什么? 4.说说你对原型和原型链的理解? 5.说说你对ES6中Generator的理解 6.说说你对Event ...

  7. 微信小程序性能优化方案

    文章目录 微信小程序性能优化方案 提高加载性能 小程序代码包准备(下载代码包) 开发者代码注入 页面渲染优化 提升渲染性能 setData工作原理 优化方法 微信小程序性能优化方案 微信小程序如果想要 ...

  8. 全平台小程序开发框架Uni-app重点概览

    1. 通过vue-cli命令行创建Uni-app 全局安装vue-cli npm install -g @vue/cli 创建uni-app vue create -p dcloudio/uni-pr ...

  9. 2018 前端性能优化清单(转载)

    2018 前端性能优化清单 转载自 https://juejin.im/post/5a966bd16fb9a0635172a50a 前言:这篇文章我在掘金翻译计划中跟着一起翻译的文章(感谢掘金翻译), ...

最新文章

  1. 切糕[HNOI2013]
  2. 多线程编程实战(一)
  3. 该文件夹包含名称过长 解决方案
  4. DPDK — PMD,DPDK 的核心优化
  5. POJ 2075 Tangled in Cables
  6. jQuery中focusin()和focus()、find()和children()的差别
  7. Hadoop LZO的安装与配置
  8. openlayers地图旋转_地图切换动画#openlayers入门笔记#
  9. Hulu 算法工程师组团帮你拿offer
  10. 物联网核心安全系列——物联网安全需求
  11. HttpComponents组件探究 - HttpClient篇
  12. SpringBoot:Unable to start LiveReload server(已解决)
  13. Bailian2710 数制转换(POJ NOI0113-01)【进制】
  14. 强悍的命令 —— cp
  15. 设计模式--观察者模式与命令模式
  16. 跟工作选择障碍同学聊一聊现实的问题……
  17. Unity UGUI —— 鼠标穿透UI问题(Unity官方的解决方法)
  18. esp8266开发入门教程(基于Arduino)——编程基础介绍
  19. ENSP模拟实验OSPF NSSA区域
  20. php图片64位处理,php实现图片以base64显示的方法

热门文章

  1. Reddit程序员的酒后真言
  2. Laravel核心解读--Database(一)基础介绍
  3. Kafka会不会重复消费
  4. pyqt5的runJavaScript 使用模板
  5. rc脚本(类的定义与脚本的结构、start方法、stop和status方法、以daemon方式启动)...
  6. 【小工匠聊Modbus】04-调试工具
  7. ubuntu配置安装KBEngine服务器
  8. C#学习笔记---数据类型
  9. IEDevToolBar - 一个分析网页的有用的工具
  10. mysql 字符串特殊字符_转:MySQL数据入库时特殊字符处理