You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

修复说明

  1. 替换scrollend事件为scroll事件+定时器的组合,确保在Firefox中也能准确检测滚动结束状态
  2. 调整scrollIntoView的定位参数为block: "start",避免跨浏览器的定位偏差
  3. 优化滚轮事件拦截逻辑,减少连续滚动时的状态冲突

内容的提问来源于stack exchange,提问作者XeroTRV3

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:03:25