2 回答

TA貢獻1836條經驗 獲得超13個贊
首先,你只需要一個?IntersectionObserver
。只要您需要相同的回調和選項(在本例中就是如此),您就可以observe()
使用同一個觀察者來處理多個元素。只有您observer.observe(i);
需要在循環內。
但是,如果您向上或向下跳轉頁面,則您的單個觀察者可以同時調用多個條目。因此,您需要循環所有觀察到的條目。
更重要的是,intersectionRatio
不關心元素在屏幕上的位置。元素在框的頂部和底部都跨越了 100% 可見性閾值。
您只關心框頂部的元素。該IntersectionObserverEntry
對象還有一個boundingClientRect
屬性可以告訴您該元素現在所在的位置。您可以使用它來僅切換頂部的元素。
所以你最終會得到這樣的結果:
const observer = new IntersectionObserver((entries) => {
? ? for (let i of entries) {
? ? ? ? i.target.classList.toggle(
? ? ? ? ? ? "is-pinned", i.boundingClientRect.y < 0);
? ? }
}, {threshold: [1]});
document.querySelectorAll(".myElement").forEach(i => observer.observe(i));
然而,這仍然給你帶來了一個問題。在您的示例中,您滾動的框足夠長,如果您直接從頂部跳到底部,則會出現從“框下方可見 0%”到“框頂部可見 99%”的元素。這不會超過 100% 閾值,因此 IntersectionObserver 回調永遠不會為這些元素觸發!這意味著他們沒有上課is-pinned。
您可以簡單地向同一個觀察者添加另一個 0% 的閾值來捕獲這些變化:
const observer = new IntersectionObserver((entries) => {
? ? for (let i of entries) {
? ? ? ? i.target.classList.toggle(
? ? ? ? ? ? "is-pinned", i.boundingClientRect.y < 0);
? ? }
}, {threshold: [0, 1]});
document.querySelectorAll(".myElement").forEach(i => observer.observe(i));
現在,從可見到粘性(或反之亦然)的元素和從不可見到粘性(或反之亦然)的元素都會切換其類。

TA貢獻1834條經驗 獲得超8個贊
你的JS最后一行犯了一個錯誤。將其更改為:
document.querySelectorAll(".myElement").forEach((i) => {
const observer = new IntersectionObserver(
([i]) => i.target.classList.toggle("is-pinned", i.intersectionRatio < 1), {
threshold: [1]
});
observer.observe(document.querySelector(".myElement")); // Use the element instead!
})
添加回答
舉報