IntersectionObserver v2版本
业务需要内容展示后日志打点,于是使用到了IntersectionObserver,实践中发现一个问题:如果内容出现在了可视区内,但是被其他元素遮挡住了,这时候仍然会打日志。
于是寻找解决方案,发现IntersectionObserver 还有一个v2版本,刚好能解决这个问题。
在v2版本中,IntersectionObserverEntry对象数组的每一项都包含一个isVisible属性,该属性标识当前元素是否可见。当设置opacity
, filter
, transform
或者被其他元素遮挡导致元素不可见时,该属性为false;
要开启该功能,需要在IntersectionObserver的配置参数中增加两个属性: trackVisibility
delay
{
trackVisibility: true,
delay: 100, // 最小100
}
下面是一个示例代码:
<div id="root">
<p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p><p></p>
</div>
<script>
// 观察根元素和被观察目标元素的交叉情况
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isVisible && entry.isIntersecting) {
entry.target.innerHTML = "loaded";
// observer.unobserve(entry.target); // 停止观察目标元素
} else {
entry.target.innerHTML = "unloaded";
}
});
},
{
// rootMargin 默认值为” 0px 0px 0px 0px “,可用百分比,相当扩展根元素的对应宽高的百分比的值;
// 可以是负值。正数的时候代表在回调会更早触发,为负值代表回调更晚触发。 为了避免出现空白,可以设置为正值
rootMargin: "-40px 0px -40px 0px ",
// root 被观察对象的祖先元素,也就是根元素;默认是浏览器的视口窗口
root: document.querySelector("#root"),
// threshold一个包含阈值的数组,比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发四次回调函数,
// 数组中的每个阈值可以是 0~1 之间的任意数值,默认值为[0],也就是开始进入,就会触发。
threshold: [1],
trackVisibility: true,
delay: 1000,
}
);
const pEl = document.querySelectorAll("p");
pEl.forEach((item) => observer.observe(item));
</script>
<style>
* {
margin: 0;
padding: 0;
}
div {
height: 400px;
overflow: auto;
box-shadow: 0 0 2px 0px rgba(255, 0, 0, 1);
margin-left: 10px;
}
p {
height: 50px;
width: 400px;
margin: 10px;
border: 1px solid darkseagreen;
/* opacity: 0.8; */
}
</style>
需要注意的是:该isVisible的判断比较保守,例如
filter: grayscale(0.01%)
或opacity: 0.99
设置也会isVisible为false。