• IntersectionObserver


    创建对象

    var io = new IntersectionObserver(callback, option);

    IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。

    构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。

    // 开始观察,参数是观察对象元素
    io.observe(document.getElementById('example'));
    
    // 停止观察
    io.unobserve(element);
    
    // 关闭观察器
    io.disconnect();

    如果要观察多个节点,就要多次调用这个方法。

    io.observe(elementA);
    io.observe(elementB);

    callback 参数

    目标元素的可见性变化时,就会调用观察器的回调函数callbackcallback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)。callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象

    const intersectionObserver = new IntersectionObserver((entries) => {
        console.log(entries);# entries 返回数组
    for (entry of entries)
    {
    if (entry.intersectionRatio > 0)
       {
        addAnimationClass(entry.target, animationClass);
    }
    else {
         console.log(animationClass); removeAnimationClass(entry.target, animationClass);
    }
    }
    }

    IntersectionObserverEntry对象一共有六个属性

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

    Option 对象

    IntersectionObserver构造函数的第二个参数是一个配置对象。它可以设置以下属性。

    6.1 threshold 属性

    threshold属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。

    new IntersectionObserver(
      entries => {/* ... */}, 
      {
        threshold: [0, 0.25, 0.5, 0.75, 1]
      }
    );

    用户可以自定义这个数组。比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。

    6.2 root 属性,rootMargin 属性

    很多时候,目标元素不仅会随着窗口滚动,还会在容器里面滚动(比如在iframe窗口里滚动)。容器内滚动也会影响目标元素的可见性,IntersectionObserver API 支持容器内滚动。root属性指定目标元素所在的容器节点(即根元素)。注意,容器元素必须是目标元素的祖先节点。

    var option = { 
      root: document.querySelector('.container'),
      rootMargin: "500px 0px" 
    };
    
    var observer = new IntersectionObserver(
      callback,
       option
    );

    上面代码中,除了root属性,还有rootMargin属性。后者定义根元素的margin,用来扩展或缩小rootBounds这个矩形的大小,从而影响intersectionRect交叉区域的大小。它使用CSS的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值。

    这样设置以后,不管是窗口滚动或者容器内滚动,只要目标元素可见性变化,都会触发观察器。

    惰性加载案例

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <!-- <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=es6"></script> -->
        <title>IntersectionObserver</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
    
            div {
                margin: 0 auto;
                max-width: 100%;
                width: 600px;
            }
    
            #top {
                height: 1200px;
                background-color: #aaaaaa;
            }
    
            #middle {
                margin-top: 200px;
                opacity: 0;
                height: 400px;
                background-color: #000000;
            }
    
            #bottom {
                height: 300px;
                background-color: #333;
            }
    
            #middle.move,
            #bottom.move {
                animation: movefromleft 2s;
                animation-fill-mode: forwards;
            }
    
            @keyframes movefromleft {
                from {
                    opacity: 0;
                    transform: translateX(-300px);
                }
                to {
                    opacity: 1;
                    transform: translateX(0px);
                }
            }
        </style>
    </head>
    
    <body>
        <div id="top"></div>
        <div id="middle"></div>
        <div id="bottom"></div>
    </body>
    <script>
        window.onload = (event) => {
            const middle = document.getElementById('middle'),
                bottom = document.getElementById('bottom');
            const animationClass = 'move';
            // 创建监听
            const intersectionObserver = new IntersectionObserver((entries) => {
                console.log(entries);
                for (entry of entries) {
                    if (entry.intersectionRatio > 0) {
                        addAnimationClass(entry.target, animationClass);
                    } else {
                        console.log(animationClass);
                        removeAnimationClass(entry.target, animationClass);
                    }
                }
            });
            // 添加动画class的操作
            function addAnimationClass(elem, animationClass) {
                elem.className.includes(animationClass) ? 1 : elem.className = elem.className + ' ' + animationClass;
            }
            // 移除动画class的操作
            function removeAnimationClass(elem, animationClass) {
                elem.className.includes(animationClass) ? elem.className = elem.className.replace(animationClass, '') : 1;
                console.log(elem.className);
            }
            // 开启监听
            intersectionObserver.observe(middle);
            intersectionObserver.observe(bottom);
        }
    
    </script>
    
    </html>
    View Code 单个元素(图片)
    const eles = document.querySelectorAll('img[data-src]')
    const observer = new IntersectionObserver( entries => {
      entries.forEach(entry => {
        if (entry.intersectionRatio > 0) {
          let oImg = entry.target
          oImg.src = oImg.getAttribute('data-src')
          observer.unobserve(oImg)
        }
      })
    }, {
      root: document.getElementById('list')
    })
    eles.forEach(item => { observer.observe(item) })
    View Code 多个图片(元素)

    注意:

    IntersectionObserver API 是异步的,不随着目标元素的滚动同步触发。

    规格写明,IntersectionObserver的实现,应该采用requestIdleCallback(),即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。

    文章引用: IntersectionObserver API 使用教程

          Intersection Observer

          图片优化

  • 相关阅读:
    分布式中各种概念汇总
    JMS
    spring boot jpa mysql
    spring boot 视图层(JAVA之学习-2)
    idea+spring boot的初学(JAVA学习之1)
    Yii在cli模式下执行一些脚本的配置
    在centos下安装django
    python简单的发送邮件
    ElasticSearch-PHP的API使用(二)
    Elasticsearch的PHP的API使用(一)
  • 原文地址:https://www.cnblogs.com/xuey/p/9253369.html
Copyright © 2020-2023  润新知