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
相关产品推荐
相关产品推荐

