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

jQuery绑定鼠标滚轮实现平滑滚动动画异常冲突问题求解

滚轮整屏滚动动画冲突卡顿问题

问题表现

需要实现的交互:每次向上/向下拨动鼠标滚轮时,分别触发平滑滚动到页面顶部#top元素、页面底部#bottom元素的动画,两个区块均设置height:100vh。
实际运行异常:页面完成一次向下滚动后就会出现无规律问题,上下滚动切换时动画互相冲突、卡顿抖动,仿佛滚动操作存在冷却期,无法及时响应输入。仅极小幅度拨动鼠标滚轮时,上下滚动功能可正常双向运行,已确认问题根源为滚动输入重叠——滚轮正常滚动时会连续触发多次事件,短时间内传入过多滚动指令,导致动画队列冲突、脚本运行异常。

初始问题代码

原生jQuery animate实现

jQuery(window).bind('mousewheel DOMMouseScroll', function(event){
    if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
        // 向上滚动
        console.log("scroll up");
        jQuery('html,body').animate({scrollTop: jQuery("#top").offset().top}, 1200, 'linear');
    }
    else {
        // 向下滚动
        console.log("scroll down");
        jQuery('html,body').animate({scrollTop: jQuery("#bottom").offset().top}, 1200, 'linear');
    }
});

jQuery.scrollTo库实现

jQuery(window).bind('mousewheel DOMMouseScroll', function(event){
    if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
        // 向上滚动
        console.log("scroll up");
        jQuery('body').scrollTo('#top', {duration:1200});
    }
    else {
        // 向下滚动
        console.log("scroll down");
        jQuery('body').scrollTo('#bottom', {duration:1200});
    }
});

配套HTML结构

<div id="top" style="height:100vh;background-color: #2196f3;"></div>
<div id="bottom" style="height:100vh;background-color: #009688;"></div>

问题核心原因

  • 滚轮事件是高频触发事件,正常拨动一次滚轮会连续触发十几次事件回调,初始代码每次回调都会往jQuery动画队列里新增一个滚动动画,队列里的动画会依次执行,直接导致动画堆积、响应延迟
  • 触发新动画前没有终止正在执行的旧动画,反向滚动时新旧动画同时作用于滚动属性,直接引发卡顿抖动
  • 没有拦截原生默认滚动行为,自定义动画和浏览器原生滚动逻辑冲突

修复方案

从三个点修复即可解决问题:

  • 触发新动画前调用.stop(true)终止选中元素上所有正在执行的动画,清空待执行的动画队列
  • 增加动画状态锁,动画执行期间直接拦截重复的滚轮事件,不新增动画任务,等当前动画执行完成后再解锁接收新输入
  • 事件回调内先调用event.preventDefault()阻止原生默认滚动行为,避免和自定义动画冲突

修复后可直接运行的代码:

// 滚动动画状态锁
let isAnimating = false;
jQuery(window).on('mousewheel DOMMouseScroll', function(event) {
    // 动画执行中直接拦截重复事件
    if (isAnimating) return;
    // 阻止原生默认滚动
    event.preventDefault();

    // 判断滚动方向,计算目标滚动位置
    const scrollToTop = event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0;
    const targetOffset = scrollToTop ? jQuery('#top').offset().top : jQuery('#bottom').offset().top;

    // 标记动画开始,终止旧动画后执行新动画
    isAnimating = true;
    jQuery('html, body').stop(true).animate({
        scrollTop: targetOffset
    }, 1200, 'linear', function() {
        // 动画执行完成,解锁
        isAnimating = false;
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:21:32