如何正确计算累计垂直滚动距离 实现导航栏平滑显隐效果
问题修复说明
存在的核心问题
- prevDirection 更新时机错误:你将
prevDirection的更新逻辑放在了toggleHeader函数中,只有当累计滚动值超过10触发显隐逻辑时,才会更新上一次滚动方向。如果连续滚动的单次距离都很小、累计值未达到阈值时切换了滚动方向,prevDirection仍会保留旧值,导致方向判断错误、累计滚动值计算异常。 - 未定义header变量:代码直接调用
header.classList操作DOM,但没有提前获取header元素,会抛出引用错误,打断正常逻辑执行。 - 缺少边界场景处理:当滚动到页面顶部/底部、
curScroll与prevScroll相等时,仍会执行不必要的计算逻辑。
修复后的完整代码
const showHideHeader = (function(){ const doc = document.documentElement; const w = window; // 补充获取header元素,选择器可根据实际站点结构调整 const header = document.querySelector("header"); const contactInfo = document.querySelector(".contact-info"); let prevScroll = w.scrollY || doc.scrollTop; let curScroll; let direction = 0; let prevDirection = 0; let cumulativeScroll = 0; let distanceScrolled = 0; const checkScroll = function() { curScroll = w.scrollY || doc.scrollTop; // 无滚动时直接返回,跳过后续逻辑 if (curScroll === prevScroll) return; distanceScrolled = Math.abs(curScroll - prevScroll); if (curScroll > prevScroll) { direction = 2; } else if (curScroll < prevScroll) { direction = 1; } if (direction === prevDirection) { cumulativeScroll += distanceScrolled; } else { cumulativeScroll = distanceScrolled; } if (cumulativeScroll > 10) { toggleHeader(direction, curScroll); } // 每次滚动计算完成后就更新方向和滚动位置,保证下一次计算的基准正确 prevDirection = direction; prevScroll = curScroll; }; const toggleHeader = function(direction, curScroll) { if (direction === 2 && curScroll > 85) { header.classList.add("home-hide"); contactInfo.classList.add("hide"); } else if (direction === 1) { header.classList.remove("home-hide"); contactInfo.classList.remove("hide"); } }; window.addEventListener('scroll', checkScroll); })();
核心修改点
- 提前获取header元素,避免引用报错
- 将
prevDirection的更新逻辑移到checkScroll函数末尾,每次滚动计算完成后就更新,保证方向判断的准确性 - 补充无滚动场景的直接返回逻辑,减少不必要的计算
- 移除
toggleHeader中冗余的方向更新逻辑
内容的提问来源于stack exchange,提问作者NekiMakiHaida
相关产品推荐
相关产品推荐

