• 详解 Intersection Observer API ( 交叉观察器 )


    一、介绍

    Intersection Observer API 提供了一种方法可以监听目标元素是否展示到视口(viewport,常见的需求场景:

    • 图片懒加载
    • 滚动动画

    上述的需求,以往一般监听 scroll 事件,利用 getBoundingClientRect()方法获取目标元素的位置信息。由于监听 scroll 事件,不断地触发回流,对性能有一定的影响,不过可以通过函数节流解决,但是 getBoundingClientRect() 方法对性能造成的影响无法有效优化的。

    !!!所以,浏览器为了解决上述难题,推出了IntersectionObserver API ,由于方法是异步的,不影响主线程的执行效率。

    二、兼容性

    兼容市面的主流浏览器,总体来说乐观,不过为了代码的严谨,简单判断下:

    if (window?.IntersectionObserver) {
    	let io = new IntersectionObserver(callback, options)
    	io.observe(targetElement)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    三、内置方法/属性

    let io = new IntersectionObserver(entries => {
    	// IntersectionObserverEntry 作为一个参数返回
    	console.log(entries)
    }, { root: null, rootMargin: '0px 0px', threshold: [0.5, 1] })
    
    // 开始监听
    io.observe(targetElement)
    // 停止监听
    io.unobserve(targetElement)
    // 结束监听器
    io.disconnect()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    以上我们可以看到,IntersectionObserver 接收一个回调函数,和一个对象options作为参数。

    IntersectionObserverEntry 实例作为entries参数被传递到回调函数,提供此时元素的相关信息。


    查看 entries 具有哪些属性:

    在这里插入图片描述

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

    API 提供的方法/属性:

    方法 / 属性作用
    root 根元素,默认视口(viewport)
    rootMargin相对根元素的偏移量,默认值为"0px 0px"
    threshold触发回调函数的门阀值,升序排列,默认0,可选:[0, 0.25, 0.5, 0.75, 1]
    observe(targetElement)开始监听,必传 targetElement,可同时观察多个节点
    unobserve(targetElement)停止监听,必传 targetElement
    takeRecords()为所有监听目标返回一个IntersectionObserverEntry对象数组并且停止监听这些目标
    disconnect()停止监听器工作

    四、使用

    我们这里写一个滚动更新元素内容/样式功能:
    在这里插入图片描述

    HTML:

    <div class="container">
      <div class="item" data-id="1">元素1:不可见</div>
      <div class="item" data-id="2">元素2:不可见</div>
      <div class="item" data-id="3">元素3:不可见</div>
      <div class="item" data-id="4">元素4:不可见</div>
      <div class="item" data-id="5">元素5:不可见</div>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    JS: 当目标元素完全暴露/非完全暴露时,修改文字/背景颜色

    <script>
      if (window?.IntersectionObserver) {
        let items = [...document.getElementsByClassName('item')] // 解析为真数组,也可用 Array.prototype.slice.call()
    
        let io = new IntersectionObserver(entries => {
          entries.forEach(item => {
            // intersectionRatio === 1说明该元素完全暴露出来
            if (item.intersectionRatio === 1) {
              item.target.style.backgroundColor = 'deeppink'
              item.target.innerHTML = `元素${item.target.getAttribute('data-id')}:完全可见`
            } else {
              item.target.style.backgroundColor = 'deepskyblue'
              item.target.innerHTML = `元素${item.target.getAttribute('data-id')}:不可见`
            }
          })
        }, {
          root: null,
          rootMargin: '0px 0px',
          threshold: 1 // 阀值设为1,当只有比例达到1时才触发回调函数
        })
    
        items.forEach(item => io.observe(item))
      }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    五、相关链接

  • 相关阅读:
    stm32实现hid鼠标
    C# Winform应用程序简介
    Android系统10 RK3399 init进程启动(三十八) property属性系统初始化代码分析
    C++ 变量的声明和初始化方式
    Python获取本机IP地址的几种方式~转
    【2021年数学建模国赛C题第一问】基于TOPSIS法评价类模型
    元宇宙|高阶音频处理能力,让声音「声临其境」
    【教学类-16-02】20221125《世界杯七巧板A4整页-随机参考图七巧板 3份一页》(大班)
    面试题:说说你了解的分布式 ID 生成方案
    Java数据库连接 (Java Database connect)
  • 原文地址:https://blog.csdn.net/Vue2018/article/details/128151898