如何在特定Div上禁用页面滚动但保留滚动交互以切换菜单?
解决方案:禁用页面滚动但保留ScrollTrigger滚动交互逻辑
核心思路
通过阻止目标区域内的原生滚动事件,同时手动模拟滚动进度传递给ScrollTrigger,既避免页面实际滚动,又保留滚动交互触发菜单项切换的逻辑,无需全局设置position:fixed或overflow:hidden。
具体实现步骤
1. 阻止目标区域的原生滚动事件
监听wheel(桌面端)和touchmove(移动端)事件,仅在#wrapper区域内阻止默认滚动行为,同时提取滚动增量用于更新ScrollTrigger进度。
// 阻止#wrapper区域内的桌面端滚动 document.addEventListener('wheel', (e) => { const wrapper = document.getElementById('wrapper'); if (wrapper.contains(e.target)) { e.preventDefault(); // 提取滚动增量,传递给ScrollTrigger scrollTriggerInstance.scroll(scrollTriggerInstance.scroll() + e.deltaY); } }, { passive: false }); // 阻止#wrapper区域内的移动端触摸滚动 let lastTouchY = 0; document.addEventListener('touchmove', (e) => { const wrapper = document.getElementById('wrapper'); if (wrapper.contains(e.target)) { e.preventDefault(); const currentTouchY = e.touches[0].clientY; const delta = currentTouchY - lastTouchY; lastTouchY = currentTouchY; // 转换触摸方向为滚动增量,传递给ScrollTrigger scrollTriggerInstance.scroll(scrollTriggerInstance.scroll() - delta); } }, { passive: false });
2. 改造ScrollTrigger实例
将ScrollTrigger实例保存为全局变量,方便手动更新滚动进度;移除scrub配置,改为通过事件触发手动控制。
let scrollTriggerInstance; let currentMenuItemIndex = 0; // 确保clamp函数存在(若全局未定义) function clamp(value, min, max) { return Math.min(Math.max(value, min), max); } // 初始化ScrollTrigger scrollTriggerInstance = ScrollTrigger.create({ trigger: '#wrapper', start: 'top top', end: 'bottom bottom', onUpdate: (self) => { const currentScrollDistance = self.scroll(); // 这里需替换为你实际定义的单段滚动距离(比如每个内容区块的高度) const scrollDistance = 300; let newMenuItemIndex = Math.floor(currentScrollDistance / scrollDistance); newMenuItemIndex = clamp(newMenuItemIndex, 0, menuItems.length - 1); if (newMenuItemIndex !== currentMenuItemIndex) { // 移除上一个菜单项的选中状态 menuItems[currentMenuItemIndex].classList.remove('selected'); contents[currentMenuItemIndex].querySelectorAll(".tags") .forEach(circle => circle.classList.remove('circle')); // 激活当前菜单项 menuItems[newMenuItemIndex].classList.add('selected'); contents[newMenuItemIndex].querySelectorAll(".tags") .forEach(circle => circle.classList.add('circle')); currentMenuItemIndex = newMenuItemIndex; } } });
优势说明
- 仅在目标区域内禁用滚动,页面其他区域可正常滚动(若业务需要)
- 无需修改全局元素布局,避免
position:fixed带来的适配问题 - 保留原生滚动的交互手感,同时通过手动控制ScrollTrigger进度实现菜单项切换逻辑
内容的提问来源于stack exchange,提问作者omie.soa
相关产品推荐
相关产品推荐

