如何在网页中部实现视差滚动?解决Intersection Observer失效问题
问题分析与修复方案
你的代码存在几个核心问题,导致视差效果错乱且Intersection Observer未按预期工作:
- 重复绑定scroll事件:每次section进入视口时,都会新增一个scroll监听,滚动时同一逻辑会被执行多次,直接造成元素位置计算混乱。
- 错误的滚动基准:直接用
window.scrollY计算偏移,没考虑section自身在页面中的位置,滚动到页面其他区域时,视差元素仍会被错误偏移。 - 未处理离开视口的情况:section离开视口后,scroll监听依然存在,会继续干扰其他区域的页面元素。
修复后的代码
const section = document.querySelector(".parallax"); const img = document.querySelectorAll("img"); const title = document.querySelector(".title"); // 存储scroll监听函数,方便后续移除 let scrollHandler = null; const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { // 获取section相对于文档顶部的位置 const sectionTop = entry.boundingClientRect.top + window.scrollY; scrollHandler = () => { // 计算当前滚动位置相对于section顶部的偏移量 const scrollOffset = window.scrollY - sectionTop; // 仅当scrollOffset大于等于0时应用视差(避免section未进入时触发) if (scrollOffset >= 0) { img[0].style.top = `-${scrollOffset / 12}px`; img[1].style.top = `-${scrollOffset / 13}px`; img[2].style.top = `-${scrollOffset / 14}px`; img[3].style.top = `-${scrollOffset / 15}px`; img[4].style.top = `-${scrollOffset / 16}px`; img[5].style.top = `-${scrollOffset / 17}px`; img[6].style.top = `-${scrollOffset / 18}px`; title.style.marginRight = `${scrollOffset}px`; } }; window.addEventListener("scroll", scrollHandler); } else { // 离开视口时移除scroll监听,重置元素位置 if (scrollHandler) { window.removeEventListener("scroll", scrollHandler); // 重置元素样式,避免影响其他区域 img.forEach(el => el.style.top = "0"); title.style.marginRight = "0"; } } }); }, { threshold: 0 }); observer.observe(section);
关键改进点
- 避免重复绑定:仅在section进入视口时绑定一次scroll监听,离开时立即移除。
- 基于section位置计算偏移:用
window.scrollY - sectionTop作为视差计算基准,确保只有滚动到section区域时才触发正确偏移。 - 离开视口重置状态:移除监听并重置元素样式,防止干扰页面其他部分的正常显示。
内容的提问来源于stack exchange,提问作者Madan Timilsina
相关产品推荐
相关产品推荐

