はじめに
IntersectionObserver は、ターゲット要素と祖先要素または最上位のドキュメント ビューポートとの交差における変化を非同期的に観察する方法を提供します。
IntersectionObserver は、コールバックとオプションの 2 つのパラメーターを受け取ります。options はオプションであり、デフォルト値があります。
const オブザーバー = 新しい IntersectionObserver(callback[, options]);
基本的な使い方
<div class="viewableArea">
指定的可视区域
<div class="target">被监听的目标元素</div>
内容很多,都多到出现滚动条了。内容很多,都多到出现滚动条了。内容很多,都多到......
</div>
const specifiedViewableArea = document.getElementsByClassName('viewableArea')[0];
const target = document.getElementsByClassName('target')[0];
const options = {
// 指定可视区域
root: specifiedViewableArea,
// 给可视区域添加”虚拟“外边距
rootMargin: '0px',
// 当目标元素与指定可视区发生交叉,且目标元素出现在可视区的部分占目标元素的比例是0.33时,触发callback的调用。
threshold: 0.33,
};
const callback = (entries: IntersectionObserverEntry[], observer?: IntersectionObserver) => {
entries.forEach((entry) => {
console.log('entry:', entry);
// todo 根据entry里的信息判断是否要你想做的事情
if (entry.isIntersecting) {
console.log('intersecting');
} else {
console.log('not intersecting');
}
});
};
// 创建并返回一个IntersectionObserver交叉观察者实例,并传入 callback回到函数 和 options配置项。
// callback 在什么时候调用? ----> 当目标元素与可视区域交叉的部分占目标元素的比例达到options设置的阈值threshold时调用。
// 两个时机:当目标元素进入可视区时、当目标元素离开可视区时。
const observer = new IntersectionObserver(callback, options);
// 开始观察目标元素
observer.observe(target);
例
例 1
const options = {
root: specifiedViewableArea,
rootMargin: '0px',
// threshold可以是一个number,值在0~1之间。
// 这里,当目标元素的只有三分之一出现在可视区时,触发callback
threshold: 0.33,
};
例 2
const options = {
root: specifiedViewableArea,
rootMargin: '0px',
// threshold 可以是一个升序的数组。
// 当目标元素在进入或离开可视区域时,交叉区域的阈值满足数组中任意一个值,都会触发callback。
threshold: [0.3, 0.7],
};
状態 1:
状態 2:
状態 3:
例 3
const options = {
root: specifiedViewableArea,
// 添加虚拟边界作为可视区的一部分,这也作为可视区和目标元素交叉的一部分。
rootMargin: '50px',
threshold: 0.25,
};
関連する API 命令
IntersectionObserver
interface IntersectionObserver {
// 要监听的可视区域,默认是顶级文档的视窗。
readonly root: Element | Document | null;
// 计算可视区交叉时添加到根(root)边界盒bounding box的矩形偏移量,默认值为"0px 0px 0px 0px"。
// 当计算交叉时,会把它看作是指定可视区的一部分。
readonly rootMargin: string;
// 一个按升序排列的阈值列表,当目标元素在进入或离开可视区域时,交叉区域的阈值满足数组中任意一个值,都会触发callback。默认值为0。
readonly thresholds: ReadonlyArray<number>;
// 停止所有监听。
disconnect(): void;
// 开始监听目标元素。
observe(target: Element): void;
// 返回所有被观察目标的记录。
takeRecords(): IntersectionObserverEntry[];
// 取消监听目标元素。
unobserve(target: Element): void;
}
IntersectionObserverEntry
このインターフェイスは、ターゲット要素が特定の遷移の瞬間に指定された可視領域と交差するときに情報を記録します。
interface IntersectionObserverEntry {
// 返回目标元素的边界信息,包括left、right、top、buttom、width、height、x、y。
readonly boundingClientRect: DOMRectReadOnly;
// 返回目标元素出现在可视区的比例。
readonly intersectionRatio: number;
// 返回目标元素和可视区的相交区域的边界信息。
readonly intersectionRect: DOMRectReadOnly;
// 当目标元素出现在可视区时返回true。当目标元素从可视区消失时返回false。这两种情况均触发callback的调用。
readonly isIntersecting: boolean;
// 可视区的边界信息。
readonly rootBounds: DOMRectReadOnly | null;
// 目标元素。
readonly target: Element;
// 从开始监听到发生交叉的时间戳。
readonly time: DOMHighResTimeStamp;
}
応用
ページがスクロールすると、アニメーション効果が実行されます
const observer = new IntersectionObserver(
(entries: IntersectionObserverEntry[]) => {
if (entries[0].intersectionRatio <= 0.33) {
// 动画相关代码...
}
},
{
root: specifiedViewableArea,
threshold: 0.33
}
);
observer.observe(target);
リソースの遅延読み込み
たとえば、画像リソースの遅延読み込みです。
const observer = new IntersectionObserver(
(entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// 加载图片的相关代码... 给img的src属性赋值
// 取消对当前元素的监听
observer.unobserve(entry.target);
}
});
}
);
// 观察所有要加载图片的元素
const imgList = document.querySelectorAll('img');
imgList.forEach((img) => observer.observe(img));
埋もれた露出
指定された可視領域にターゲット要素が完全に表示されたら、埋没点露光を実行します。
const observer = new IntersectionObserver(
(entries: IntersectionObserverEntry[]) => {
entries.forEach((entry) => {
// 目标元素完全暴露在可视区域中
if (entry.intersectionRatio === 1) {
//埋点曝光相关代码...
// 取消对当前元素的监听
observer.unobserve(entry.target);
}
});
},
{
root: null,
threshold: 1,
}
);
// 观察要进行埋点曝光的元素
observer.observe(target)
参照研究
MDN ドキュメント: https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver
ナゲット記事: https://juejin.cn/post/6844903874302574599