intersection observer之初认识

背景

以往,判断某个元素是否进入了“视口”,传统的方法都是监听“scroll”事件,调用某元素的getBoundingClientRec()方法获取位置信息来判断是否在视口内,但是由于scroll事件密集发生,计算量大容易导致性能问题。

浏览器原生提供的IntersectionObserver API ,可以“自动观察”元素是否是可见,由于可见的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"。

传统判断元素进入视口的实现方式

调用元素的getBoundingClientRec()方法获取位置信息

实现思路: 

  • 获取浏览器的视口宽高
    • window.innerHeight || document.documentElement.clientHeight
    • window.innerWidth || document.documentElement.clientWidth
  • 获取元素的位置信息  element.getBoundingClientRect()
  • 元素在视窗内会满足以下条件:
    • 当top >=0(即往上滚动),top要 <= 视窗的高度; 当 top < 0(即往下滚动),bottom >= 0

    • 当left >=0(即往右滚动),left要 <= 视窗的宽度;当 left < 0(即往左边滚动),right >= 0

const isVisible = (dom) => {
   const viewHeight = window.innerHeight || document.documentElement.clientHeight
   const viewWidth = window.innerWidth || document.documentElement.clientWidth
   const { top, left, right, bottom} = dom
   // 当元素在垂直方向上都有在可视窗区域内,则判断在水平方向上元素是否在可视窗区域内
   if((top >= 0 && top <= viewHeight) || (top < 0 && bottom >= 0)) {
      return left >= 0 ? left <= viewWidth : right >= 0 
    }
    // 如果没进入到上述条件 意味着元素不在视窗内
    return false
  }

通过intersection observer来实现监听

Intersection Observer是一种异步观察目标元素的方法,因此他接受一个回调函数callback作为参数,第二个参数是option可配置项

具体的参数介绍可查看文档:Intersection Observer - Web API 接口参考 | MDN

const box = document.getElementById('box')
// 创建观察实例
const io = new IntersectionObserver((entries) => {
   // 接收的参数entries是一个数组,每个成员都是一个IntersectionObserverEntry对象
   console.log(entries)
})
  // 传入目标元素开始观察
io.observe(box)

 注意:观察者中的回调函数一般会触发两次。一次是目标元素开始进入视口时触发,另一次是目标元素完全离开视口时触发

 回调函数中每个成员(IntersectionObserverEntry 对象) 里重要属性介绍:

boundingClientRect: 包含目标元素的位置信息和宽 (bottom/left/right/top/height/width/x/y)
intersectionRatio: 指目标元素出现在可视区域的比例
intersectionRect: 指目标元素和可视区域的相交区域
isIntersecting: 返回一个布尔值,如果目标元素出现在可视区域则为true 如果从可视区域完全消失否则为false
rootBounds: 根元素矩形区域的位置信息和大小 一般默认是视口
target: 被观察的目标元素

从以上属性可以得知,我们可以拿到属性“isIntersecting” 来判断目标元素是否在可视区域内了

const io = new IntersectionObserver((entries) => {
   entries.forEach(entry => {
      console.log(entry.isIntersecting ? '显示' : '消失')
    })
})

实现给出现的目标元素增加样式效果

思路:

  • 观察对象中isIntersecting属性来给在视窗的目标元素切换类名
  • 需要延时触发回调函数,达到视觉上切换类名展现样式的过渡效果

想要控制回调函数的触发时机,需要使用第二个参数配置对象,设置" threshold "

new IntersectionObserver((entries) => {
   // threshold 设置了0.8 意味着目标元素出现视窗80%时才会触发
   console.log('目标元素出现在视窗80%了')
}, { threshold: 0.8 })

下面实现的案例:获取所有的li标签元素,给li标签出现在视窗50%的元素添加一个active类名

// 获取所有li标签
const items = document.querySelectorAll('li')
// 创建观察实例
const io = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        const { target, isIntersecting } = entry
        // 给目标元素添加类名
        target.classList.toggle('active', isIntersecting)
    })
}, {
    threshold: 0.5. // 表示目标元素出现在视窗的50%才会触发回调
})

// 遍历获取的元素 观察所有元素
items.forEach(element => io.observe(element)

观察元素进入视口的应用场景

最常见的场景就是图片的懒加载和列表的无限滚动,以往的做法都是通过监听scroll去实现。

具体的如何使用IntersectionObserver去实现这两种场景,后续再发布文章。

~~~end~~~

猜你喜欢

转载自blog.csdn.net/weixin_45313351/article/details/128193919