IntersectionObserver
介绍
IntersectionObserver 翻译为 "交叉观察者"。提供了一种异步观察目标元素与其祖先元素(默认是顶级文档视窗)交叉状态的方法,祖先元素被称为根(root)。
1、IntersectionObserver 是异步的,不随着目标元素的滚动同步触发。底层应该是采用requestIdleCallback()
,即只有线程空闲下来,才会执行观察器。这意味着,这个观察器的优先级非常低,只在其他任务执行完,浏览器有了空闲才会执行。
2、必须是子元素跟祖先元素发生交叉。
语法
1、构造函数
const io = new IntersectionObserver(cb,options);
2、回调函数
发生交叉的回调,接受一个entries参数,是一个数组,返回当前已监听并且发生了交叉的目标集合
new IntersectionObserver(entries => {
entries.forEach(entry => console.log(entry));
// ...
});
我们看看entry里面包含哪些常用属性:
属性 | 说明 |
---|---|
target | 目标元素 |
rootBounds | 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null |
boundingClientRect | 目标元素的矩形区域的信息 |
intersectionRect | 目标元素与视口(或根元素)的交叉区域的信息 |
intersectionRatio | 目标元素可见区域的占比,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0 |
isIntersecting | 字面理解为是否正在交叉,可用做判断目标元素是否可见,为true时,目标元素从不可见到可见,为false时,目标元素从可见到不可见。 |
3、options
顾名思义,它是一个配置参数,对象类型,非必填,有3个属性如下:
属性 | 说明 |
---|---|
root | 指定祖先元素,默认为视窗 |
rootMargin | 触发交叉的偏移值,默认为"0px 0px 0px 0px"(上左下右,正数为向外扩散,负数则向内收缩) |
threshold | 该属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个阈值,如[0, 0.25, 0.5, 0.75, 1],默认为[0] |
4、实例方法
属性 | 说明 | 参数 |
---|---|---|
observe | 开始监听一个目标元素 | 节点 |
unobserve | 停止监听一个目标元素 | 节点 |
takeRecords | 返回所有监听的目标元素集合 | |
disconnect | 停止所有监听 |
实例
图片懒加载
<div class="parent">
<div>
<img class="child" data-origin="some-real-url.jpg" />
</div>
...
</div>
let parent = document.querySelector(".parent");
let childs = document.querySelectorAll(".child");
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
item.target.src = item.target.dataset.origin; // 开始加载图片
observer.unobserve(item.target); // 停止监听已开始加载的图片
}
});
}, {
root: parent,
});
childs.forEach(item => { observer.observe(item); });
动画展示
相信很多人都需要过这种需求,当某个元素出现的时候就给该元素加个动画,比如渐变、偏移等;
<ul>
<li></li> // 多个li
</ul>
li.show {
/* 默认从左边进来 */
animation: left 1s ease;
}
li.show:nth-child(2n) {
/* 偶数从右边进来 */
animation: right 1s ease;
}
@keyframes left {
from {
opacity: 0;
transform: translate(-20px, 20px);
}
to {
opacity: 1;
}
}
@keyframes right {
from {
opacity: 0;
transform: translate(20px, 20px);
}
to {
opacity: 1;
}
}
let list = document.querySelectorAll("ul li");
let observer = new IntersectionObserver(entries => {
entries.forEach(item => {
if (item.isIntersecting) {
item.target.classList.add("show"); // 增加show类名
observer.unobserve(item.target); // 移除监听
}
});
});
list.forEach(item => observer.observe(item));
浏览器兼容性
IE不兼容,不过有官方的polyfill,链接地址为:polyfill
MutationObserver
ResizeObserver
PerformanceObserver
参考资料
现代浏览器支持的不同类型的观察者
轻轻松松实现高难度懒加载、吸顶、触底
IntersectionObserver API 使用教程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。