ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 语法 ``` interface IntersectionObserverInit { root?: Element | Document | null; //必须是目标元素的父级元素 rootMargin?: string; threshold?: number | number[]; // 如果想可见成都每多25%执行一次,则写 [0, 0.25, 0.5, 0.75, 1] } interface IntersectionObserver { readonly root: Element | Document | null; readonly rootMargin: string; //rootMargin: '0px 0px -200px 0px' , // 写法类似 margin //0px 0px -200px 0px,表示容器的下边缘向上收缩200像素, //导致页面向下滚动时,目标元素的顶部进入可视区域200像素以后,才会触发回调函数 readonly thresholds: ReadonlyArray<number>; disconnect(): void; observe(target: Element): void; takeRecords(): IntersectionObserverEntry[]; unobserve(target: Element): void; } declare var IntersectionObserver: { prototype: IntersectionObserver; new(callback: IntersectionObserverCallback, options?: IntersectionObserverInit): IntersectionObserver; }; ``` 回调函数的参数说明 `callback`会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见) ``` // 回调函数有两个参数 interface IntersectionObserverCallback { (entries: IntersectionObserverEntry[], observer: IntersectionObserver): void; } interface IntersectionObserverEntry { readonly boundingClientRect: DOMRectReadOnly; //目标元素的矩形区域的信息 readonly intersectionRatio: number; // 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0 readonly intersectionRect: DOMRectReadOnly; //目标元素与视口(或容器元素)的交叉区域的信息 readonly isIntersecting: boolean; readonly rootBounds: DOMRectReadOnly | null; // 容器元素的矩形区域的信息,getBoundingClientRect()方法的返回值 readonly target: Element; //被观察的目标元素,是一个 DOM 节点对象 readonly time: number; //可见性发生变化的时间,是一个高精度时间戳,单位为毫秒 } ``` ## 判断是否可见 ``` new IntersectionObserver( function (entries) { // 如果不可见,就返回 if (entries[0].intersectionRatio <= 0) return; loadItems(10); console.log('Loaded new items'); } ); ``` ## 实例 ## hello world 默认在viewport 中可看性监听 <details> <summary>main.html</summary> ``` /** * * @param {IntersectionObserverEntry[]} entry * @param {IntersectionObserver} Observer * @constructor */ let Observer=function (entry, Observer) { console.log(entry); } let intersectionObserver = new IntersectionObserver(Observer) intersectionObserver.observe(document.querySelector("img")) ``` </details> <br/> ### 惰性加载(lazy load) <details> <summary>main.html</summary> ``` // html <img src="placeholder.png" data-src="img-1.jpg"> <img src="placeholder.png" data-src="img-2.jpg"> <img src="placeholder.png" data-src="img-3.jpg"> //js function query(selector) { return Array.from(document.querySelectorAll(selector)); } var observer = new IntersectionObserver( function(entries) { entries.forEach(function(entry) { entry.target.src = entry.target.dataset.src; observer.unobserve(entry.target); }); } ); query('.lazy-loaded').forEach(function (item) { observer.observe(item); }); ``` </details> <br/> ### 无限滚动 <details> <summary>main.html</summary> ``` var intersectionObserver = new IntersectionObserver( function (entries) { // 如果不可见,就返回 if (entries[0].intersectionRatio <= 0) return; loadItems(10); console.log('Loaded new items'); } ); // 开始观察 intersectionObserver.observe( document.querySelector('.scrollerFooter') ); ``` </details> <br/> ### 视频自动播放 <details> <summary>main.html</summary> ``` // html <video src="foo.mp4" controls=""></video> // js 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); ``` </details> <br/>