IntersectionObserver API 详解篇(2)

下面这句话很重要,IntersectionObserver API 的基本工作原理就是:当目标元素和根元素相交的面积占目标元素面积的百分比到达或跨过某些指定的临界值时就会触发回调函数。threshold 参数就是用来指定那个临界值的,默认值是 0,表示俩元素刚刚挨上就触发回调。有效的临界值可以是在 0 到 1 闭区间内的任意数值,比如 0.5 表示当相交面积占目标元素面积的一半时触发回调。而且可以指定多个临界值,用数组形式,比如 [0, 0.5, 1],表示在两个矩形开始相交,相交一半,完全相交这三个时刻都要触发一次回调函数。如果你传了个空数组,它会给你自动插入 0,变成 [0],也等效于默认值 0。

<

下面的动画演示了当 threshold 参数为 [0, 0.5, 1] 时,向下滚动页面时回调函数是在何时触发的:

不仅当目标元素从视口外移动到视口内时会触发回调,从视口内移动到视口外也会:

你可以在这个 demo 里验证上面的两个动画:

你可以在这个 demo 里验证上面的两个动画:

<div> 慢慢向下滚动,相交次数: <span>0</span> </div> <div></div> <style> #info { position: fixed; } #target { position: absolute; top: 200%; width: 100px; height: 100px; background: red; margin-bottom: 100px; } </style> <script> let observer = new IntersectionObserver(() => { times.textContent = +times.textContent + 1 }, { threshold: [0, 0.5, 1] }) observer.observe(target) </script>

threshold 数组里的数字的顺序没有强硬要求,为了可读性,最好从小到大书写。如果指定的某个临界值小于 0 或者大于 1,浏览器会报错:

<script> new IntersectionObserver(() => {}, { threshold: 2 // SyntaxError: Failed to construct 'Intersection': Threshold values must be between 0 and 1. }) </script>

rootMagin

本文一开始就说了,这个 API 的主要用途之一就是用来实现延迟加载,那么真正的延迟加载会等 img 标签或者其它类型的目标区块进入视口才执行加载动作吗?显然,那就太迟了。我们通常都会提前几百像素预先加载,rootMargin 就是用来干这个的。rootMargin 可以给根元素添加一个假想的 margin,从而对真实的根元素区域进行缩放。比如当 root 为 null 时设置 rootMargin: "100px",实际的根元素矩形四条边都会被放大 100px,像这样:

IntersectionObserver API 详解篇

效果可以想象到,如果 threshold 为 0,那么当目标元素距离视口 100px 的时候(无论哪个方向),回调函数就提前触发了。考虑到常见的页面都没有横向滚动的需求,rootMargin 参数的值一般都是 "100px 0px",这种形式,也就是左右 margin 一般都是 0px. 下面是一个用 IntersectionObserver 实现图片在距视口 500px 的时候延迟加载的 demo:

<div>图片在页面底部,仍未加载,请向下滚动</div> <img src="https://www.jb51.net/data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=" data-src="https://img.alicdn.com/bao/uploaded/i7/TB1BUK4MpXXXXa1XpXXYXGcGpXX_M2.SS2"> <style> #info { position: fixed; } #img { position: absolute; top: 300%; } </style> <script> let observer = new IntersectionObserver(() => { observer.unobserve(img) info.textContent = "开始加载图片!" img.src = img.dataset.src }, { rootMargin: "500px 0px" }) observer.observe(img) </script>

注意 rootMargin 的值虽然和 CSS 里 margin 的值的格式一样,但存在一些限制,rootMargin 只能用 px 和百分比两种单位,用其它的单位会报错,比如用 em:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwfjsd.html