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!
})
添加回答
举报