Intersection Observer

创建

  1. 创建一个 IntersectionObserver 对象,并传入相应参数和回调用函数,该回调函数将会在目标(target)元素和根(root)元素的交集大小超过阈值(threshold)规定的大小时候被执行。
js 复制代码
const ob = new IntersectionObserver(callback, option)
  1. callback: 交叉改变后运行: 交叉/不交叉 => 不交叉/交叉
  2. option: 配置项目
  • root: 指定根(root)元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。
  • rootMargin: 根(root)元素的外边距。类似于 CSS 中的 margin 属性,比如 "10px 20px 30px 40px" (top, right, bottom, left)。如果有指定 root 参数,则 rootMargin 也可以使用百分比来取值。该属性值是用作 root 元素和 target 发生交集时候的计算交集的区域范围,使用该属性可以控制 root 元素每一边的收缩或者扩张。默认值为 0。
  • threshold: 阈值!可以是单一的 number 也可以是 number 数组,target 元素和 root 元素相交程度达到该值的时候 IntersectionObserver 注册的回调函数将会被执行。如果你只是想要探测当 target 元素的在 root 元素中的可见性超过 50%的时候,你可以指定该属性值为 0.5。如果你想要 target 元素在 root 元素的可见程度每多 25%就执行一次回调,那么你可以指定一个数组[0, 0.25, 0.5, 0.75, 1]。默认值是 0(意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为 1.0 含义是当 target 完全出现在 root 元素中时候 回调才会被执行。
  1. IntersectionObserver Entry

IntersectionObserverEntry 对象提供了目标元素与跟元素相交的详细信息。他有如下几个属性。

typescript 复制代码
interface IntersectionObserverEntry {
  readonly attribute DOMHighResTimeStamp time;
  readonly attribute DOMRectReadOnly? rootBounds;
  readonly attribute DOMRectReadOnly boundingClientRect;
  readonly attribute DOMRectReadOnly intersectionRect;
  readonly attribute boolean isIntersecting;
  readonly attribute double intersectionRatio;
  readonly attribute Element target;
};
  • time:发生相交到相应的时间,毫秒。
  • rootBounds:根元素矩形区域的信息,如果没有设置根元素则返回 null,图中蓝色部分区域。
  • boundingClientRect:目标元素的矩形区域的信息,图中黑色边框的区域。
  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息,图中蓝色方块和粉红色方块相交的区域。
  • isIntersecting:目标元素与根元素是否相交(满足预设的阈值条件)
  • intersectionRatio:目标元素与视口(或根元素)的相交比例。
  • target:目标元素,图中黑色边框的部分。
js 复制代码
var observer = new IntersectionObserver((entries) => {
  for (const entry of entries) {
    console.log(entry.time) // 发生变化的时间
    console.log(entry.rootBounds) // 根元素的矩形区域的信息
    console.log(entry.boundingClientRect) // 目标元素的矩形区域的信息
    console.log(entry.isIntersection) // 目标元素与视口(或根元素)是否相交(满足预设的阈值条件)
    console.log(entry.intersectionRect) // 目标元素与视口(或根元素)的交叉区域的信息
    console.log(entry.intersectionRatio) // 目标元素与视口(或根元素)的相交比例
    console.log(entry.target) // 被观察的目标元素
  }
}, {})

// 开始观察某个目标元素
observer.observe(target)

// 停止观察某个目标元素
observer.unobserve(target)

// 关闭监视器
observer.disconnect()

// 获取所有 IntersectionObserver 观察的 targets
observer.takeRecords()

请留意,你注册的回调函数将会在主线程中被执行。所以该函数执行速度要尽可能的快。如果有一些耗时的操作需要执行,建议使用 Window.requestIdleCallback() 方法。

所有区域均被 Intersection Observer API 当做一个矩形看待。如果元素是不规则的图形也将会被看成一个包含元素所有区域的最小矩形,相似的,如果元素发生的交集部分不是一个矩形,那么也会被看作是一个包含他所有交集区域的最小矩形。

这个有助于理解 IntersectionObserverEntry 的属性,IntersectionObserverEntry 用于描述 targetroot 的交集。

应用

图片懒加载

html 复制代码
<!-- html -->
<img src='default.png' data-src="xxxxx" />
<img src='default.png' data-src="xxxxx" />
<img src='default.png' data-src="xxxxx" />
<img src='default.png' data-src="xxxxx" />
js 复制代码
// js
const ob = new IntersectionObserver(
  entries => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        ob.unobserve(img);
      }
    }
  },
  {
    root: null,
    rootMargin: 0,
    threshold: 0
  }
);

const imgs = document.querySelectorAll('img[data-src]')
imgs.forEach(img => {
  ob.observe(img)
})

下拉加载更多

方式:在dom元素之下存在一个加载动画。当加载动画出现在视口中,继续添加dom元素

html 复制代码
  <div>
    // 省略其他dom元素...
  </div>
  <loading></loading>
js 复制代码
const ob = new IntersectionObserver(
  entries => {
    if (entries[0].isIntersecting) {
      // ...添加doms
    }
  },
  {
    root: null,
    rootMargin: '0',
    threshold: 0
  }
);
const loading = document.querySelector('.loading');
ob.observe(loading);
相关推荐
Yvonne爱编码36 分钟前
CSS- 4.1 浮动(Float)
前端·css·html·github·html5·hbuilder
timeguys1 小时前
【前端】[vue3] [uni-app]使用 vantUI 框架
前端·uni-app
岁岁岁平安1 小时前
Vue3学习(组合式API——Watch侦听器、watchEffect()详解)
前端·javascript·vue.js·学习·watch侦听器·组合式api
uwvwko2 小时前
BUUCTF——web刷题第一页题解
android·前端·数据库·php·web·ctf
有事没事实验室2 小时前
CSS 浮动与定位以及定位中z-index的堆叠问题
前端·css·开源
2501_915373882 小时前
Vue路由深度解析:Vue Router与导航守卫
前端·javascript·vue.js
小妖6663 小时前
前端表格滑动滚动条太费事,做个浮动滑动插件
前端
读心悦3 小时前
5000 字总结CSS 中的过渡、动画和变换详解
前端·css·tensorflow
__BMGT()3 小时前
C++ QT 打开图片
前端·c++·qt
仍然探索未知中3 小时前
前端扫盲HTML
前端·html