携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
💻文档地址:ahooks.js.org/zh-CN/
👨💻github地址:github.com/alibaba/hoo…
先来认识一个 API
Intersection Observer
IntersectionObserver接口 (从属于Intersection Observer API) 提供了一种异步观察目标元素与其祖先元素或顶级文档视窗 (viewport) 交叉状态的方法。祖先元素与视窗 (viewport) 被称为根 (root)。
当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。一旦 IntersectionObserver 被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;然而,你可以在同一个观察者对象中配置监听多个目标元素。
浏览器兼容
还不错,基本上都可以使用 (中间那个 IE 就不用管了)
一句话:Intersection Observer API 提供给开发者,一种异步查询元素相对于其他元素或窗口位置的能力,常用于追踪一个元素在窗口的可视问题。
var io = new IntersectionObserver(
entries => {
console.log(entries);
}
);
entries 是一个数组,每个成员都是一个IntersectionObserverEntry对象。IntersectionObserverEntry对象提供目标元素的信息,一共有六个属性。
time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒target:被观察的目标元素,是一个 DOM 节点对象rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回nullboundingClientRect:目标元素的矩形区域的信息intersectionRect:目标元素与视口(或根元素)的交叉区域的信息intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0isIntersecting:是一个布尔值,当目标元素与交集观察者的根元素相交时为真。
function useInViewport(target: BasicTarget, options?: Options) {
const [state, setState] = useState<boolean>();
const [ratio, setRatio] = useState<number>();
useEffectWithTarget(
() => {
const el = getTargetElement(target);
if (!el) {
return;
}
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
setRatio(entry.intersectionRatio);
setState(entry.isIntersecting);
}
},
{
...options,
root: getTargetElement(options?.root),
},
);
observer.observe(el);
return () => {
observer.disconnect();
};
},
[],
target,
);
return [state, ratio] as const;
}
IntersectionObserver Option 是 IntersectionObserver 构造函数的第二个参数,用来配置监视器的部分信息。
- root:设置监视器的根节点,不传则默认为视口。
- rootMargin: 类似于 CSS 的 margin 属性。用来缩小或扩大 rootBounds,从而影响相交的触发。
- threshold:属性决定相交比例为多少时,触发回调函数。取值为 0 ~ 1,或者 0 ~ 1的数组。 如下图,当我们把 threshold 设置为 [0, 0.25, 0.5, 0.75, 1],绿色方块分别在 0%,25%,50%,75%,100% 可见时,触发回调函数。
const [inViewport, ratio] = useInViewport(() => document.getElementById('children'), {
threshold: [0, 0.25, 0.5, 0.75, 1],
root: () => document.getElementById('parent'),
});
参考文章: