Firefox下JavaScript实现的滚动功能异常问题求助
多色块页面平滑滚动Firefox异常问题修复
我用下方代码实现了全屏色块页面间的平滑滚动(仅4天JavaScript开发经验),功能在Chrome中可以正常工作,但在Firefox里出现异常:单次滚动滚轮1格时切换正常,连续滚动多格会出现卡顿并停止切换。
原始代码
JavaScript
const ScrollDelay = 130; var LastScrollTime = Date.now(); var NewScrollTime = Date.now(); var IsScrolling = false; var CurrentPage; function GotoPage(PageNumber) { PageNumber = Math.min(Math.max(PageNumber, 1), 5); if (CurrentPage == PageNumber) { return false; } document.getElementById("Page"+PageNumber).scrollIntoView({behavior: "smooth", inline: "center"}) } function ScrollStart(Wheel) { NewScrollTime = Date.now(); if (!Wheel) { return false; } Wheel.preventDefault(Wheel); Wheel.stopPropagation(Wheel); if ((NewScrollTime - LastScrollTime) < ScrollDelay || IsScrolling == true) { return false; } IsScrolling = true; if (Wheel.deltaY < 0) { GotoPage(CurrentPage - 1); } else { GotoPage(CurrentPage + 1); } LastScrollTime = Date.now(); return false; } function ScrollEnd() { CurrentPage = Math.min(Math.max(Math.round(window.scrollY / innerHeight) + 1, 1), 5); } window.onload = function() { CurrentPage = Math.round(window.scrollY / window.innerHeight) + 1; } window.addEventListener("wheel", ScrollStart, {passive: false}); document.onscrollend = (event) => { ScrollEnd(); IsScrolling = false; };
CSS
* { font: 16px Verdana, sans-serif; padding: 0px; margin: 0px; } :root::-webkit-scrollbar { width: 0; height: 0; } /* Pages */ .PageContainer { padding: 0; margin: 0; } .Page { width: 100%; height: 100vh; padding: 0; margin: 0; } #Page1 { background-color: darkred; } #Page2 { background-color: green; } #Page3 { background-color: purple; } #Page4 { background-color: darkblue; } #Page5 { background-color: brown; }
HTML
<!DOCTYPE html> <html lang="en"> <head> <link rel="stylesheet" href="index.css"> </head> <body> <script src="Main.js"></script> <div class="PageContainer"> <div class="Page" id="Page1"></div> <div class="Page" id="Page2"></div> <div class="Page" id="Page3"></div> <div class="Page" id="Page4"></div> <div class="Page" id="Page5"></div> </div> </body> </html>
问题原因
Firefox对scrollend事件的触发时机和Chrome存在差异,连续滚动时scrollend不会及时触发,导致IsScrolling一直处于true状态,后续滚轮事件被直接拦截。同时Firefox中scrollIntoView的平滑滚动逻辑与Chrome也有区别,进一步加剧了卡顿问题。
修复方案
修改滚动结束的检测逻辑,改用scroll事件结合定时器判断滚动停止状态,同时调整状态管理逻辑:
const ScrollDelay = 130; const ScrollEndTimeout = 200; // 判定滚动停止的超时阈值 var LastScrollTime = Date.now(); var IsScrolling = false; var CurrentPage; var scrollEndTimer; function GotoPage(PageNumber) { PageNumber = Math.min(Math.max(PageNumber, 1), 5); if (CurrentPage == PageNumber) { return; } // 改用block: "start"保证页面定位更精准 document.getElementById("Page"+PageNumber).scrollIntoView({behavior: "smooth", block: "start"}) } function ScrollStart(Wheel) { const now = Date.now(); if ((now - LastScrollTime) < ScrollDelay || IsScrolling) { Wheel.preventDefault(); Wheel.stopPropagation(); return; } IsScrolling = true; LastScrollTime = now; Wheel.deltaY < 0 ? GotoPage(CurrentPage - 1) : GotoPage(CurrentPage + 1); Wheel.preventDefault(); Wheel.stopPropagation(); } function handleScroll() { // 滚动过程中不断重置定时器,超时后判定滚动结束 clearTimeout(scrollEndTimer); scrollEndTimer = setTimeout(() => { CurrentPage = Math.min(Math.max(Math.round(window.scrollY / window.innerHeight) + 1, 1), 5); IsScrolling = false; }, ScrollEndTimeout); } window.onload = function() { CurrentPage = Math.round(window.scrollY / window.innerHeight) + 1; } window.addEventListener("wheel", ScrollStart, {passive: false}); window.addEventListener("scroll", handleScroll);
修复说明
- 替换
scrollend事件为scroll事件+定时器的组合,确保在Firefox中也能准确检测滚动结束状态 - 调整
scrollIntoView的定位参数为block: "start",避免跨浏览器的定位偏差 - 优化滚轮事件拦截逻辑,减少连续滚动时的状态冲突
内容的提问来源于stack exchange,提问作者XeroTRV3
相关产品推荐
相关产品推荐

