業務需要內容展示後日誌打點,於是使用到了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。