Add/remove class 到 div 如果部分在视口中(vanilla JS)

Add/remove class to div if section is in viewport (vanilla JS)

我有一个包含 5 个部分的单页纸,每个部分的最小高度为 100vh 和一个 ID。 然后有一个固定的背景div,当新的部分进入视口时它会改变它的状态。

<div class="background"></div>

<section id="s1">...</section>
<section id="s2">...</section>
<section id="s3">...</section>
<section id="s4">...</section>
<section id="s5">...</section>

我想更新背景 div 为 class ,在该部分进入视口时使用当前部分 ID 的名称,并在该部分离开视口时将其删除。

这是我做的:

const sections = document.querySelectorAll('section')
const bg = document.querySelector('div.background')

document.addEventListener('scroll', updateBg)

function updateBg() {
  sections.forEach((section) => {
    const pixels = window.pageYOffset
    const sectionId = section.getAttribute('id')
    const offsetBottom = section.offsetTop + section.offsetHeight

    if (section.offsetTop <= pixels) {
      bg.classList.add(sectionId)
    }

    else if (offsetBottom >= pixels) {
        bg.classList.remove(sectionId)
      }

    else {
      bg.classList.remove(sectionId)
    }
  })
}

当部分进入视口时添加当前 class 效果很好。但是当这些部分离开视口时,它并没有删除 classes,就像我在 else if (offsetBottom >= pixels) 语句中声明的那样。当我完全向下滚动页面时,我有这样的东西:

<div class="background s1 s2 s3 s4 s5"></div>

但我最后想要的是: <div class="background s5"></div>

有什么帮助吗?

您的条件似乎不正常。您正在为所有低于滚动阈值的部分设置 class。相反,如果该部分的一部分可见,则应添加 class,否则应将其删除,如下所示:

if (section.offsetTop <= pixels && offsetBottom > pixels) {
  bg.classList.add(sectionId);
} else {
  bg.classList.remove(sectionId)
}

另外,请阅读这个问题的答案:How can I tell if a DOM element is visible in the current viewport? 建议使用 getBoundingClientRect API 代替。