原生JS实现section进入视口时为背景div增删类名问题求解
问题根源
你的判断逻辑存在缺陷:仅判断了滚动偏移量大于等于区块顶部就添加类名,没有同时校验是否还未滚动超出区块底部。这就导致所有你已经滚动经过的区块,对应的类名会被全部添加上,不会触发移除逻辑。
修复方案1:调整原有滚动监听逻辑
修改updateBg里的判断条件,仅当滚动位置处于当前区块的垂直范围内时才添加对应类名,否则直接移除,同时增加节流逻辑避免性能损耗:
const sections = document.querySelectorAll('section') const bg = document.querySelector('div.background') let isTicking = false document.addEventListener('scroll', updateBg) function updateBg() { if (!isTicking) { window.requestAnimationFrame(() => { const scrollY = window.pageYOffset sections.forEach((section) => { const sectionId = section.id const sectionTop = section.offsetTop const sectionBottom = sectionTop + section.offsetHeight // 仅当滚动位置落在当前区块范围内时加类,否则移除 if (scrollY >= sectionTop && scrollY < sectionBottom) { bg.classList.add(sectionId) } else { bg.classList.remove(sectionId) } }) isTicking = false }) isTicking = true } } // 页面加载后先执行一次,避免初始状态类名异常 updateBg()
修复方案2:使用IntersectionObserver(更推荐)
用浏览器原生交叉监听API实现,不需要手动计算偏移量,性能更优:
const sections = document.querySelectorAll('section') const bg = document.querySelector('div.background') const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { const sectionId = entry.target.id if (entry.isIntersecting) { bg.classList.add(sectionId) } else { bg.classList.remove(sectionId) } }) }, { // 阈值可自定义,0.5代表区块50%进入视口时触发状态切换 threshold: 0.5 }) // 给所有section注册交叉监听 sections.forEach(section => observer.observe(section))
内容的提问来源于stack exchange,提问作者mollini
相关产品推荐
相关产品推荐

