react框架 typescript语言 自定义了一个wheelpicker组件,但是滚轮滚动一下会划过三个选项,没办法准确的选择其中一个,想问问大家有没有什么办法可以解决这个问题
import React, { useRef, useEffect } from 'react';
import { Box, List, ListItem } from '@mui/material';
interface WheelPickerProps {
range: number[];
onSelect: (value: number) => void;
}
const WheelPicker: React.FC<WheelPickerProps> = ({ range, onSelect }) => {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const container = containerRef.current;
if (container) {
const handleScroll = () => {
const scrollPosition = container.scrollTop + container.clientHeight / 2;
const itemHeight = container.children[0].clientHeight;
const selectedIndex = Math.round(scrollPosition / itemHeight) - 1; // 减去上方占位元素的高度
if (selectedIndex >= 0 && selectedIndex < range.length) {
const selectedValue = range[selectedIndex];
onSelect(selectedValue);
}
};
container.addEventListener('scroll', handleScroll);
return () => {
container.removeEventListener('scroll', handleScroll);
};
}
}, [range, onSelect]);
return (
<Box
sx={{
position: 'relative',
height: '200px',
width: '100px',
backgroundColor: '#333', // 设置背景颜色
}}
>
<Box
ref={containerRef}
sx={{
height: '100%',
overflowY: 'auto',
scrollBehavior: 'smooth',
scrollSnapType: 'y proximity', // 使用 proximity 吸附功能
'&::-webkit-scrollbar': { display: 'none' }, // 隐藏滚动条
}}
>
<List sx={{ padding: 0, margin: 0 }}>
{/* 上方的占位元素 */}
<ListItem
sx={{
height: '80px', // 高度设置为遮罩区两倍
}}
/>
{range.map((value, index) => (
<ListItem
key={index}
sx={{
height: '40px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
scrollSnapAlign: 'center',
scrollSnapStop: 'always', // 确保滚动停止在每个元素上
fontSize: '20px',
color: index === 0 || index === range.length - 1 ? '#888' : '#fff',
}}
onClick={() => onSelect(value)}
>
{value}
</ListItem>
))}
{/* 下方的占位元素 */}
<ListItem
sx={{
height: '80px', // 高度设置为遮罩区两倍
}}
/>
</List>
</Box>
{/* 遮罩Box被放置在容器Box的外部 */}
<Box
sx={{
position: 'absolute',
top: '50%',
left: 0,
right: 0,
height: '40px',
marginTop: '-20px',
backgroundColor: 'rgba(255, 255, 255, 0.1)', // 设置遮罩的颜色
pointerEvents: 'none',
border: '2px solid #1976d2',
borderRadius: '4px',
zIndex: 1, // 确保遮罩在列表项之上
}}
/>
</Box>
);
};
export default WheelPicker;