如何使用JS实现滚动时根据方向跳转至下一个/上一个锚点
实现滚动方向触发锚点自动跳转
你已经有了一套点击可跳转至对应锚点的垂直导航栏,现在要实现滚动页面时根据滚动方向,自动跳转到下一个或上一个锚点,以下是具体实现方案:
原始导航栏HTML代码
<div id="top-menu" class="verticalNav textCenter"> <ul class="bg-dark-transparent"> <li><a id="scroll1" class="liColor noTextDecoration sideMenu" href="#introduction">Intro</a></li> <li><a id="scroll2" class="liColor noTextDecoration sideMenu" href="#overview">Overview</a></li> <li><a id="scroll3" class="liColor noTextDecoration sideMenu" href="#process">Process</a></li> <li><a id="scroll4" class="liColor noTextDecoration sideMenu" href="#research">Research</a></li> <li><a id="scroll5" class="liColor noTextDecoration sideMenu" href="#analysis">Analysis</a></li> <li><a id="scroll6" class="liColor noTextDecoration sideMenu" href="#ideation">Ideation</a></li> <li><a id="scroll7" class="liColor noTextDecoration sideMenu" href="#prototype">Prototype</a></li> <li><a id="scroll8" class="liColor noTextDecoration sideMenu" href="#testing">Testing</a></li> <li><a id="scroll9" class="liColor noTextDecoration sideMenu" href="#result">Result</a></li> </ul> </div>
核心实现逻辑(JavaScript)
通过监听滚动事件判断方向,定位当前锚点后触发对应锚点的平滑跳转,同时用防抖避免频繁触发:
// 获取所有导航链接和对应的锚点目标元素 const navLinks = document.querySelectorAll('.sideMenu'); const anchorTargets = Array.from(navLinks).map(link => document.querySelector(link.getAttribute('href'))); // 记录上一次滚动位置,用于判断滚动方向 let lastScrollTop = 0; // 防抖定时器,防止滚动事件频繁触发 let scrollTimer = null; // 防抖函数封装 function debounce(func, delay) { return function() { clearTimeout(scrollTimer); scrollTimer = setTimeout(func, delay); }; } // 滚动事件处理逻辑 function handleScroll() { const currentScrollTop = window.pageYOffset || document.documentElement.scrollTop; const isScrollDown = currentScrollTop > lastScrollTop; // 找到当前处于视口范围内的锚点索引 const currentAnchorIndex = anchorTargets.findIndex(target => { const rect = target.getBoundingClientRect(); // 以元素进入视口1/3位置作为触发条件,可根据需求调整 return rect.top <= window.innerHeight / 3 && rect.bottom >= window.innerHeight / 3; }); if (currentAnchorIndex === -1) { lastScrollTop = currentScrollTop; return; } // 根据滚动方向确定目标锚点索引 let targetIndex; if (isScrollDown) { targetIndex = currentAnchorIndex + 1; // 到达最后一个锚点时停止跳转 if (targetIndex >= anchorTargets.length) return; } else { targetIndex = currentAnchorIndex - 1; // 到达第一个锚点时停止跳转 if (targetIndex < 0) return; } // 平滑滚动到目标锚点 anchorTargets[targetIndex].scrollIntoView({ behavior: 'smooth', block: 'start' // 可选改为'center'让锚点居中显示 }); // 更新导航激活状态(可选,给当前锚点的导航链接加样式) navLinks.forEach(link => link.classList.remove('active')); navLinks[targetIndex].classList.add('active'); lastScrollTop = currentScrollTop; } // 给窗口绑定防抖后的滚动事件监听 window.addEventListener('scroll', debounce(handleScroll, 300));
可选:添加导航激活状态样式
给当前激活的导航链接加样式,让用户明确当前位置:
.sideMenu.active { color: #fff; background-color: rgba(0,0,0,0.6); /* 可根据需求自定义其他样式 */ }
注意事项
- 确保页面中存在所有导航链接指向的锚点元素(如
id="introduction"、id="overview"等),否则代码会报错。 - 防抖时间(300ms)可按需调整,数值越大触发越不频繁,反之则更灵敏。
- 视口触发条件(
window.innerHeight / 3)也可自定义,比如改成window.innerHeight / 2,让元素居中时触发跳转。
内容的提问来源于stack exchange,提问作者SJ War
相关产品推荐
相关产品推荐

