zoukankan      html  css  js  c++  java
  • 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

          图片优化

  • 相关阅读:
    mybatis 错误 Invalid bound statement (not found)
    Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
    bug 记录 Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans
    解决:The Tomcat connector configured to listen on port 8182 failed to start. The port may already be in use or the connector may be misconfigured.
    jquery validate 验证插件 解决多个相同的Name 只验证第一个的方案
    phpStorm+xdebug调试(php7.3)
    小程序视频多个视频播放与暂停
    CSS实现单行、多行文本溢出显示省略号(…)
    Packet for query is too large (4,544,730 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.
    idea自动在文件头中添加作者和创建时间
  • 原文地址:https://www.cnblogs.com/xuey/p/9253369.html
Copyright © 2011-2022 走看看