IntersectionObserver--交叉观察器

黄粱一梦2024-05-1015

初识Intersectionobserver

Intersectionobserver 接口(从属于 Intersection 0bserver API)提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的方法。其祖先元素或视口被称为根(rot)。当一个 Intersectionobserver 对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 Intersectionoberver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配詈监听多个目标元素。

构造函数

创建一个新的’Intersectionobserver’对象,当其监听到目标元素的可见部分(的比例)超过了一个或多个闹值(threshold)时,会执行指定的回调函数

let observer =new Intersectionobserver()
// 由此就创建了-个Intersectionobserver 实例对象

实例属性

IntersectionObserver.root 只读
测试交叉时,用作边界盒的元素或文档。如果构造函数未传入 root 或其值为null,则默认使用顶级文档的视口。

IntersectionObserver.rootMargin 只读
计算交叉时添加到根边界盒的矩形偏移量,可以有效的缩小或扩大根的判定范围从而满足计算需要。此属性返回的值可能与调用构造函数时指定的值不同,因此可能需要更改该值,以匹配内部要求。所有的偏移量均可用像素(px)或百分比(%)来表达,默认值为“0px 0px 0px 0px”。

IntersectionObserver.thresholds 只读
一个包含阈值的列表,按升序排列,列表中的每个阈值都是监听对象的交叉区域与边界区域的比率。当监听对象的任何阈值被越过时,都会生成一个通知(Notification)。如果构造器未传入值,则默认值为 0。

实例方法

IntersectionObserver.disconnect()
使 IntersectionObserver 对象停止监听目标。

IntersectionObserver.observe()
使 IntersectionObserver 开始监听一个目标元素。

IntersectionObserver.takeRecords()
返回所有观察目标的 IntersectionObserverEntry 对象数组。

IntersectionObserver.unobserve()
使 IntersectionObserver 停止监听特定目标元素。

// 开始观察
observer.observe(document.getElementById('example'));

// 停止观察
observer.unobserve(element);

// 关闭观察器
observer.disconnect();

IntersectionObserverEntry 对象

{
  time: 3893.92,
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  boundingClientRect: ClientRect {
     // ...
  },
  intersectionRect: ClientRect {
    // ...
  },
  intersectionRatio: 0.54,
  target: element
}

属性含义

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

示例

简单用法

const intersectionObserver = new IntersectionObserver((entries) => {
  // 如果 intersectionRatio 为 0,则目标在视野外,
  // 我们不需要做任何事情。
  if (entries[0].intersectionRatio <= 0) return;

  loadItems(10);
  console.log("Loaded new items");
});
// 开始监听
intersectionObserver.observe(document.querySelector(".scrollerFooter"));

场景应用·图片懒加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IntersectionObserver交叉监视器</title>
    <style> *{
        padding: 0px;
        margin: 0px;
    }
    .scroll-one {
        width: 100%;
        height: 100vh;
        background-color: #ececec;
    }
    .scroll-two {
        width: 200px;
        display: flex;
        flex-wrap: wrap;
        justify-content: space-between;
        align-items: center;
        background-color: beige;
        margin: 0 auto;
    }
    .scroll-two img {
        width: 50%;
        margin: 100px 0px;
    }
    .scroll-tree {
        width: 100px;
        height: 1500px;
        margin-top: 50vh;
        background-color: pink;
    }
    </style>
</head>
<body>
    <div class="scroll-one">1</div>
    <div class="scroll-two">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
        <img src="./images/logo.png" data-src="./images/head.png" alt="" srcset="">
    </div>
    <script src="./index.js"></script>
</body>
</html>
let observer = new IntersectionObserver((entries) => {
    entries.forEach((item) => {
        if (item.isIntersecting) {
            item.target.src = item.target.dataset.src;
            // 替换成功后,停止观察该dom
            observer.unobserve(item.target);
        }
    })
}, {
    root: null
})

let one = document.querySelector('.scroll-one')
let two = document.querySelector('.scroll-two')
let images = document.querySelectorAll('.scroll-two img')

images.forEach(image => {
    observer.observe(image)
})

场景应用·视频加载

下面是一个视频元素,希望它完全进入视口的时候自动播放,离开视口的时候自动暂停。

<video src="foo.mp4" controls=""></video>
let video = document.querySelector('video');
let isPaused = false;

let observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.intersectionRatio != 1  && !video.paused) {
      video.pause();
      isPaused = true;
    } else if (isPaused) {
      video.play();
      isPaused=false;
    }
  });
}, {threshold: 1});

observer.observe(video);

上面代码中,IntersectionObserver()的第二个参数是配置对象,它的threshold属性等于1,即目标元素完全可见时触发回调函数。

参考链接

分类:随笔

标签:随笔

上一篇使用xlsx-js-style进行数据导出excel并个性化表格下一篇unveilr 文档

版权声明

本文系作者 @黄粱一梦 转载请注明出处,文中若有转载的以及参考文章地址也需注明。\(^o^)/~

Preview