跳到主要内容

Slider

demo

development

Slider 组件实现的思路:

  • 监听桌面端MouseEventMouseEvent分为以下几个阶段
  1. mousedown: 鼠标按键点击事件,可以通过button属性判断点击的按键;mousedownclick事件主要的不同点是click事件还伴随着mouseup事件的完成,而mousedown是鼠标按键点击后立即触发;
  2. mousemove: 鼠标移动事件
  3. mouseup: 鼠标按键释放事件
  • 判断鼠标点击按键是否是左键,如果是左键则通过addEventListener再次监听mousemovemouseup事件,这里不能通过在元素上设置 React 的onMouseMoveonMouseUp事件,具体原因不详;
  const handleMouseDown: React.MouseEventHandler<HTMLDivElement> = e => {
// 判断鼠标按键是不是左键
if (e.button !== 0) {
return;
}
// 阻止选取元素
e.preventDefault();

document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', cancelMove);
};
  • 通过mousemove事件的clientX属性获取鼠标光标移动过程中在页面可视区域内的坐标;
  • 通过getBoundingClientRect获取滑块父元素相对于页面可视区域左侧的left坐标(可能为负值),这样通过clientX-left的方式直接得到滑块元素相对于父元素左侧的偏移量,再除以父元素的宽度,就可以得到偏移量百分比;
  const handleMouseMove = (e: MouseEvent) => {
const { left = 0, width } = containerRef.current?.getBoundingClientRect() ?? {};
const { clientX } = e;
// 滑块滑动的偏移百分比,不随 min 和 max 变化
const leftPercent = (clientX - left) * 100 / width!;
};
  • 但是,由于滑块的绝对定位特性,所以其左右滑动的位置可能会超过父元素宽度,所以要把百分比限制在[0, 100]之间,这里通过一个clamp函数来实现:
function clamp(value: number, min: number, max: number) {
if (value == null) {
return min;
}
return Math.min(Math.max(min, value), max);
}

clamp(leftPercent, 0, 100)
  • 得到真正的偏移量百分比以后,还需要将这个百分比转换成Slider组件的minmax之间确定的值,毕竟minmax一定都是[0, 100],这里通过percentToValue函数来实现:
function percentToValue(percent: number, min: number, max: number) {
return (max - min) * percent + min;
}

相反,如果将外界给定的值转换成百分比的话,使用valueToPercent函数:

function valueToPercent(value: number, min: number, max: number) {
return ((value - min) * 100) / (max - min);
}