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

React中如何启用鼠标滚轮实现容器水平滚动?

解决方案

一、修复拖拽滚动失效问题

你的拖拽逻辑未生效,核心原因是useState的异步更新特性:scrollLeft状态更新后,handleMouseMove中拿到的仍是旧值,导致滚动偏移计算错误。将startX、scrollLeft换成useRef存储即可,ref的值是同步更新的:

const scrollRef = useRef(null);
const isDragging = useRef(false);
const startX = useRef(0);
const scrollLeft = useRef(0);

const handleMouseDown = (e) => {
  if (!scrollRef.current) return;
  isDragging.current = true;
  startX.current = e.pageX - scrollRef.current.offsetLeft;
  scrollLeft.current = scrollRef.current.scrollLeft;
  scrollRef.current.style.cursor = "grabbing";
};

const handleMouseUp = () => {
  isDragging.current = false;
  if (scrollRef.current) {
    scrollRef.current.style.cursor = "grab";
  }
};

const handleMouseMove = (e) => {
  if (!isDragging.current || !scrollRef.current) return;
  e.preventDefault();
  const x = e.pageX - scrollRef.current.offsetLeft;
  const scrollOffset = x - startX.current;
  scrollRef.current.scrollLeft = scrollLeft.current - scrollOffset;
};

二、实现鼠标滚轮水平滚动

给容器添加onWheel事件,阻止默认垂直滚动行为,将滚轮的垂直偏移转为水平滚动:

const handleWheel = (e) => {
  if (!scrollRef.current) return;
  e.preventDefault(); // 阻止页面垂直滚动
  // 可调整10的大小控制滚动速度
  scrollRef.current.scrollLeft += e.deltaY * 10;
};

更新JSX,补充onWheel事件:

<div 
  className="scrollMenu" 
  onMouseDown={handleMouseDown} 
  onMouseUp={handleMouseUp} 
  onMouseMove={handleMouseMove}
  onWheel={handleWheel}
  ref={scrollRef}
>
  <div>{mosaic()}</div>
</div>

三、优化CSS样式

添加光标样式提升拖拽体验,可选隐藏默认滚动条:

.scrollMenu {
  overflow: auto;
  white-space: nowrap;
  cursor: grab; /* 默认拖拽光标 */
}

.scrollMenu:active {
  cursor: grabbing; /* 拖拽中光标 */
}

/* 可选:自定义滚动条样式 */
.scrollMenu::-webkit-scrollbar {
  height: 6px;
}

.scrollMenu::-webkit-scrollbar-thumb {
  background-color: #ccc;
  border-radius: 3px;
}

完整代码示例

import { useRef } from 'react';

const YourComponent = () => {
  const scrollRef = useRef(null);
  const isDragging = useRef(false);
  const startX = useRef(0);
  const scrollLeft = useRef(0);

  const handleMouseDown = (e) => {
    if (!scrollRef.current) return;
    isDragging.current = true;
    startX.current = e.pageX - scrollRef.current.offsetLeft;
    scrollLeft.current = scrollRef.current.scrollLeft;
    scrollRef.current.style.cursor = "grabbing";
  };

  const handleMouseUp = () => {
    isDragging.current = false;
    if (scrollRef.current) {
      scrollRef.current.style.cursor = "grab";
    }
  };

  const handleMouseMove = (e) => {
    if (!isDragging.current || !scrollRef.current) return;
    e.preventDefault();
    const x = e.pageX - scrollRef.current.offsetLeft;
    const scrollOffset = x - startX.current;
    scrollRef.current.scrollLeft = scrollLeft.current - scrollOffset;
  };

  const handleWheel = (e) => {
    if (!scrollRef.current) return;
    e.preventDefault();
    scrollRef.current.scrollLeft += e.deltaY * 10;
  };

  const mosaic = () => {
    return (
      <>
        {Array.from({length: 20}).map((_, idx) => (
          <div key={idx} style={{display: 'inline-block', width: '200px', height: '150px', margin: '0 10px', backgroundColor: '#f0f0f0'}}>
            项 {idx+1}
          </div>
        ))}
      </>
    );
  };

  return (
    <div 
      className="scrollMenu" 
      onMouseDown={handleMouseDown} 
      onMouseUp={handleMouseUp} 
      onMouseMove={handleMouseMove}
      onWheel={handleWheel}
      ref={scrollRef}
    >
      <div>{mosaic()}</div>
    </div>
  );
};

export default YourComponent;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:52:46