滚轮滚动问题:如何设置单次滚动仅切换一个页面区块?
滚轮滚动问题:如何设置单次滚动仅切换一个页面区块?
我明白你的问题啦——用鼠标滚轮的时候这个全屏滚动效果很顺畅,但用笔记本触控板滚动时,经常会一下跳两个区块,确实很影响体验。这主要是因为触控板的wheel事件会连续触发多次(每次的deltaY数值比较小但频繁),而且原代码没有阻止浏览器的默认滚动行为,两者叠加就导致了“跳两次”的问题。
下面是调整后的代码,完全用原生JS实现,完美解决了触控板的问题:
优化后的完整代码
HTML
<div id="sections-wrap"> <div class="section"> <h2>First Section</h2> </div> <div class="section"> <h2>Second Section</h2> </div> <div class="section"> <h2>Third Section</h2> </div> <div class="section"> <h2>Fourth Section</h2> </div> </div>
CSS
html, body { margin: 0; padding: 0; height: 100%; overflow: hidden; } #sections-wrap { width: 100%; height: 100%; /* 把过渡效果移到CSS中,无需每次滚动重复设置 */ transition: transform 1s ease-in-out; } .section { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; font-size: 2rem; color: white; } .section:nth-child(1) { background: #ff5733; } .section:nth-child(2) { background: #33ff57; } .section:nth-child(3) { background: #3357ff; } .section:nth-child(4) { background: #ff33a1; }
JavaScript
let sections = document.querySelectorAll(".section") let sectionsWrap = document.getElementById("sections-wrap") let currentSectionIndex = 0 let isScrolling = false let scrollToSection = (index) => { sectionsWrap.style.transform = `translateY(-${index * 100}%)` } window.addEventListener("wheel", (event) => { // 1. 阻止浏览器默认滚动行为,避免和自定义滚动冲突 event.preventDefault(); if (isScrolling) return; // 2. 设置滚动幅度阈值,过滤触控板的微小滚动触发 const deltaThreshold = 50; if (Math.abs(event.deltaY) < deltaThreshold) return; if (event.deltaY > 0 && currentSectionIndex < sections.length - 1) { currentSectionIndex++ } else if (event.deltaY < 0 && currentSectionIndex > 0) { currentSectionIndex-- } else { return } isScrolling = true scrollToSection(currentSectionIndex) // 3. 超时时间和过渡时长匹配,避免过早或过晚解锁滚动 setTimeout(() => { isScrolling = false }, 1100) }, { passive: false }) // 4. 必须设置passive: false才能调用preventDefault()
关键修改点说明
- 阻止默认滚动行为:通过
event.preventDefault()禁用浏览器原生滚动,同时设置passive: false(现代浏览器默认wheel事件为passive: true,无法阻止默认行为),彻底避免原生滚动和自定义滚动的冲突。 - 过滤微小滚动触发:给
deltaY设置阈值,只处理幅度足够大的滚动事件,过滤掉触控板单次滚动产生的多个微小触发信号。 - 优化过渡属性位置:把
transition从JS移到CSS中,减少重复代码,逻辑更清晰。 - 匹配超时与过渡时长:将
setTimeout时长调整为1100ms,和CSS中1s的过渡时长更匹配,既不会让用户等待太久,也能确保滚动过程中不会被重复触发。
这样修改后,不管是鼠标滚轮还是笔记本触控板,每次滚动都只会切换一个区块,体验就完全一致啦~
备注:内容来源于stack exchange,提问作者Mohd Akarm
相关产品推荐
相关产品推荐

