• Intersection Observer API探索


    我们经常遇到这样的需求——检测一个元素是否可见或者两个元素是否相交,如

    ● 图片懒加载——当图片滚动到可见时才进行加载
    ● 内容无限滚动——也就是用户滚动到接近内容底部时直接加载更多,而无需用户操作翻页,给用户一种网页可以无限滚动的错觉
    ● 检测广告的曝光情况——为了计算广告收益,需要知道广告元素的曝光情况
    ● 在用户看见某个区域时执行任务或播放动画

    Element.getBoundingClientRect()

    返回一个 DOMRect 对象,其提供了元素的大小及其相对于视口的位置。

    缺点:事件监听和调用都是在主线程上运行,因此频繁触发、调用,造成浏览器频繁的重绘和回流,给网站带来相当大的卡顿

    Intersection Observer API

    window对象上有一个Intersection Observer API,它会注册一个回调函数,每当被监视的元素进入或者退出另外一个元素时 (或者 viewport ),或者两个元素的相交部分大小发生变化时,该回调方法会被触发执行。这样,我们网站的主线程不需要再为了监听元素相交而辛苦劳作,浏览器会自行优化元素相交管理。

    用法

    1. 创建一个 intersection observer

    ● 创建一个 IntersectionObserver 对象,并传入相应参数和回调用函数,该回调函数将会在目标 (target) 元素和根 (root) 元素的交集大小超过阈值 (threshold) 规定的大小时候被执行。

    let options = {
      root: document.querySelector('#scrollArea'),
      rootMargin: '0px',
      threshold: 1.0
    }
    //回调函数只会在元素达到thresholds 规定的阈值时才会执行。
    let observer = new IntersectionObserver(callback, options);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    属性说明
    root必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。
    threshold目标 (target) 元素与根 (root) 元素之间的交叉比 (intersection ratio)取值在 0.0 和 1.0 之间。可以是单一的 number 也可以是 number 数组,默认值是 0 (意味着只要有一个 target 像素出现在 root 元素中,回调函数将会被执行)。该值为 1.0 含义是当 target 完全出现在 root 元素中时候 回调才会被执行。
    rootMargin用来扩大或者缩小视窗的的大小

    若rootMargin: ‘30px 100px 20px’ 如下图所示:
    蓝线表示定义的root元素,添加rootMargin属性后,将原视窗增大,虚线就是现在的视窗,所以元素现在也就在视窗里面了。

    在这里插入图片描述

    let callback =(entries, observer) => {
      entries.forEach(entry => {
        // entry.boundingClientRect  返回包含目标元素的边界信息
        //entry.rootBounds 返回根元素的边界信息
        // entry.intersectionRatio.  返回intersectionRect 与 boundingClientRect 的比例值。
        // entry.intersectionRect.  用来描述根和目标元素的相交区域。
        // entry.isIntersecting 
        //返回一个布尔值,如果目标元素与根相交,则返回true. 如果返回false, 变换是从交叉状态到非交叉状态。
        // entry.target 与根出现相交区域改变的元素
      });
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    打印出来如下:
    在这里插入图片描述

    1. 给定一个目标元素进行观察
    let target = document.querySelector('#listItem');
    observer.observe(target);
    //unobserve()	停止监听特定目标元素
    
    • 1
    • 2
    • 3

    请留意,你注册的回调函数将会在主线程中被执行。所以该函数执行速度要尽可能的快。如果有一些耗时的操作需要执行,建议使用 Window.requestIdleCallback() 方法

    1. 停止监听特定目标元素
    observer.unobserve(target);//例如图片懒加载时,加载完后即停止监听该元素
    
    • 1
    1. IntersectionObserver对象停止全部监听工作
    observer.disconnect();
    
    • 1

    Intersection Observer的缺点

    1. IntersectionObservers中的回调是在主线程中运行的,数据是异步传递的,这意味着我们的回调函数的调用优先级是比较低的,要等到浏览器空闲时才能执行。因此使用此api完成类似滚动相关的动画注定失败,因为数据在你使用它的时候已经过时了。

    2.api只是告诉我们元素什么时候进入视窗中,但是它没告诉我们元素是否被页面其他内容挡住了,或者元素的可视display是否被改成了其他效果 (transform, opacity, filter, etc)。对于顶级文档中的元素,可以通过分析 javascript 中的 DOM 或通过 elementFromPoint() 来判断。 但是对于 iframe 中的元素,则束手无策
    进阶:Intersection Observer V2 新增isVisible布尔字段,当该字段为true时可以保证元素一定可见,而没有被遮挡,并且它的options中新增两个字段:

    trackVisibility:指示观察者是否将跟踪目标可见性的变化
    delay:Set a minimum delay between notifications

    3.Should I Use One IntersectionObserver Instance? Or One Per Element?

    4.root的设置对结果有影响
    threshhold的设置:https://javascript.tutorialink.com/intersectionobserver-does-not-work-on-small-screens-for-long-sections-js/

    参考链接:

    https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API
    https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect
    https://web.dev/intersectionobserver-v2/
    https://developer.chrome.com/blog/intersectionobserver/#what-is-intersectionobserver-not-about
    https://www.w3.org/TR/intersection-observer/
    https://www.bennadel.com/blog/3946-using-intersectionobserver-and-ngswitch-to-defer-template-bindings-in-angular-11-0-5.htm
    https://github.com/w3c/IntersectionObserver/issues/81

  • 相关阅读:
    DETR纯代码分享(三)coco_panoptic.py
    MAC 安装maven详细教程
    SQL Server 技术100问?
    Transformer模型 | Python实现TransformerCPI模型(pytorch)
    (二)正则表达式——捕获
    【项目源码】一套基于springboot+Uniapp框架开发的智慧医院3D人体导诊系统源码
    [hadoop全分布部署]安装Hadoop、配置Hadoop 配置文件②
    Python自动操作电脑|pywin32
    【自定义字符串排序】
    Alibaba(商品详情)API接口
  • 原文地址:https://blog.csdn.net/qq_38397338/article/details/138216181