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

JavaScript滚轮事件实现水平滚动卡顿问题优化咨询

解决鼠标滚轮水平滚动卡顿问题

原代码中鼠标滚轮滚动卡顿的核心原因是:直接通过scrollContainer.scrollLeft += evt.deltaY修改滚动位置是瞬间完成的硬跳转,没有过渡动画,导致视觉上的卡顿感。以下是两种可行的优化方案:

方案1:CSS原生平滑滚动(最简实现)

直接给滚动容器添加scroll-behavior: smooth样式,浏览器会自动处理平滑过渡,无需复杂JS逻辑:

main {
  scroll-behavior: smooth;
}

同时调整滚轮事件的滚动步长,避免原生deltaY值过大导致滚动过快:

scrollContainer.addEventListener("wheel", (evt) => {
  evt.preventDefault();
  // 用系数缩小滚动幅度,0.3可根据需求调整
  const scrollStep = evt.deltaY * 0.3;
  scrollContainer.scrollLeft += scrollStep;
});

方案2:JS自定义平滑动画(精细控制)

如果需要自定义动画曲线、滚动速度等细节,可使用requestAnimationFrame实现渐进式滚动,同时兼容原有拖拽逻辑:

const scrollContainer = document.querySelector("main");

let isDown = false;
let startX;
let scrollLeft;
// 平滑滚动相关变量
let isScrolling = false;
let targetScrollLeft = 0;

// 原有拖拽逻辑保持不变
scrollContainer.addEventListener('mousedown', (e) => {
  isDown = true;
  startX = e.pageX - scrollContainer.offsetLeft;
  scrollLeft = scrollContainer.scrollLeft;
  // 拖拽时终止平滑动画,避免冲突
  isScrolling = false;
});

scrollContainer.addEventListener('mouseleave', () => isDown = false);
scrollContainer.addEventListener('mouseup', () => isDown = false);

scrollContainer.addEventListener('mousemove', (e) => {
  if(!isDown) return;
  e.preventDefault();
  const x = e.pageX - scrollContainer.offsetLeft;
  const walk = (x - startX) * 2;
  scrollContainer.scrollLeft = scrollLeft - walk;
  // 更新目标位置,确保动画同步
  targetScrollLeft = scrollContainer.scrollLeft;
});

// 平滑滚动动画函数
function smoothScroll() {
  if (!isScrolling) return;
  // 计算当前位置与目标位置的差值
  const diff = targetScrollLeft - scrollContainer.scrollLeft;
  // 用衰减系数实现减速效果,0.1可调整
  const step = diff * 0.1;
  
  if (Math.abs(step) < 0.5) {
    // 差值足够小时直接定位,结束动画
    scrollContainer.scrollLeft = targetScrollLeft;
    isScrolling = false;
  } else {
    scrollContainer.scrollLeft += step;
    requestAnimationFrame(smoothScroll);
  }
}

// 优化后的滚轮事件
scrollContainer.addEventListener("wheel", (evt) => {
  evt.preventDefault();
  // 调整滚动步长,0.3可根据需求修改
  targetScrollLeft += evt.deltaY * 0.3;
  // 限制滚动范围,防止超出容器边界
  targetScrollLeft = Math.max(0, Math.min(targetScrollLeft, scrollContainer.scrollWidth - scrollContainer.clientWidth));
  
  if (!isScrolling) {
    isScrolling = true;
    requestAnimationFrame(smoothScroll);
  }
});

核心优化说明

  • 步长控制:通过evt.deltaY * 系数缩小单次滚动的幅度,避免一次性移动100px的突兀感
  • 平滑过渡:无论是CSS原生特性还是JS动画,都让滚动位置在多帧中逐步变化,模拟自然的滚动惯性
  • 逻辑兼容:拖拽时终止平滑动画,避免两种滚动逻辑相互干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:58:35