这里是Tao的文章集Web前端之路

Intersection Observer 简介

2019-12-04  本文已影响0人  MrTT

Intersection Observer API提供了一种异步观察目标元素与祖先元素或顶级文档viewport的交集中的变化的方法。这使得以往较难实现的功能,更加简单,例如,监听图片元素,在适当的时候懒加载图片。

例子

先看下,下面是一个简单的小例子

<div id="e1" style="background-color:black;width:100%;height:500px;">
  <ul style="color:white;">
    <li>boundingClientRect:<span id="el-boundingClientRect"></span></li>
    <li>intersectionRatio:<span id="el-intersectionRatio"></span></li>
    <li>intersectionRect:<span id="el-intersectionRect"></span></li>
    <li>isIntersecting:<span id="el-isIntersecting"></span></li>
    <li>rootBounds:<span id="el-rootBounds"></span></li>
    <li>time:<span id="el-time"></span></li>
  </ul>
</div>
var observer = new IntersectionObserver((entries,observer) => {
  // 我只监听了一个对象
  let entry = entries[0]
  document.querySelector("#el-boundingClientRect").innerHTML = JSON.stringify(entry.boundingClientRect);
  document.querySelector("#el-intersectionRatio").innerHTML = JSON.stringify(entry.intersectionRatio);
  document.querySelector("#el-intersectionRect").innerHTML = JSON.stringify(entry.intersectionRect);
  document.querySelector("#el-isIntersecting").innerHTML = JSON.stringify(entry.isIntersecting);
  document.querySelector("#el-rootBounds").innerHTML = JSON.stringify(entry.rootBounds);
  document.querySelector("#el-time").innerHTML = JSON.stringify(entry.time);
  //document.querySelector("el-target").innerHTML = entry.target;
}, {
  threshold : [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
});
observer.observe(document.querySelector("#e1"));

简书上由于安全原因,不能植入js脚本,所以无法预览,如果你希望预览例子,请前往我的博客

构造器

通过例子,我们可以看到Intersection Observer需要通过构造器来创建,即new IntersectionObserver(callback[, options]),参数有两部分组成,一个必传的回调函数以及一个可选的配置参数

回调Callback

Intersection Observer的翻译就是“交点观察”,因此,他的回调就成了重点。当观察元素与根元素之间的交叉状态发生变化时,它会将这部分信息反馈回来--通过回调告知

在回调函数里,我们会接受到两个对象,发生状态变化的元素集合以及监听者本身(注意:创建时,会将所有被观察元素的状态传递过来),监听者本身我们可以通过它增加或者减少监听的元素或者销毁自身(后续讲),这里我们更关注观察元素

function callback(entries,observer) {
  entries -> 一系列被观察的元素
  observer -> 观察者
}

entries 是一个 IntersectionObserverEntry 对象的数组,IntersectionObserverEntry 包换以下元素(来自MDN)

具体的值是多少,我们可以在最上面的例子中看到,需要注意传递过来的对象都是只读(毕竟回调,只是通知你发生变化了)

参数options

我们可以通过 options 配置 IntersectionObserver,他包含以下几项配置

在上面的例子中,我未修改root与rootMargin,你可以将浏览器的窗口作为可见区域,threshold定义了一系列数组,意味着到达那些交叉比时触发回调

属性

在创建或者回调函数中,我们可以得到 IntersectionObserver 对象,他包含以下属性:

IntersectionObserver 的属性也都是只读,他在创建之后不支持修改

方法

IntersectionObserver 通过以下方法添加或者取消监听元素

真实的例子

简书上由于安全原因,不能植入js脚本,所以无法预览,如果你希望预览例子,请前往我的博客

懒加载

IntersectionObserver 可以很简单的实现图片懒加载,开头就提到的,看下面很少的代码,我们就实现了懒加载的功能(目前已经好像图片懒加载框架使用它了,比如lozad.js)

<img id="e2-lazy" load-url="/images/avatar.jpg" />
var observer = new IntersectionObserver((entries,observer) => {
  let entry = entries[0]
  if (entry.isIntersecting) {
    let el = entry.target;
    el.src = el.getAttribute('load-url');
  }
});
observer.observe(document.querySelector("#e2-lazy"));

TOC 自动定位

我的博客(Cake与NexT主题)的侧边栏,它使用的就是IntersectionObserver。不过在使用时,也遇到了些问题。比如,IntersectionObserver 在浏览器中的优先级不高(高效,必然也有缺陷),如果你很快的移动,可能无法触发

我们(NexT团队)第一次尝试时,并未考虑优先级的事情,我们根据标题元素的是否在浏览器窗口可见计算其toc的位置,但如果快速滑动,那么toc的定位就会错乱

后续,我们调整,扩大根窗口的区域(与文章一样长)的方式,那么我们只需要判断是不是已经交叉即可,即便滑动太快也无需担心

相关的代码可以见:

本文作者: Mr.J
本文链接: https://www.dnocm.com/articles/beechnut/intersection-observer-info/
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

上一篇 下一篇

猜你喜欢

热点阅读