【发布时间】:2021-01-24 16:42:15
【问题描述】:
我有这个带有两个拇指的滑块。拇指可以沿着滑块(线)移动,这可以通过增加或减少他们的margin-left来实现,但是为了让他们移动状态move必须是true,它发生在每个拇指触发事件onClickDown。但是,如果触发事件onClickedUp,光标离开拇指或滑块的区域,move 设置为false,是什么使拇指停止移动。没关系,就是这样。
问题是光标可能比拇指移动更快,如下图所示,是什么让光标离开拇指区域并将move设置为false,即使那不是用户想要的。
因此,为了使滑块正常工作,用户在移动拇指时必须非常小心,这是一个非常烦人的用户体验。
简而言之,我需要做的是确保光标的移动速度不会超过拇指,我是否必须减慢光标或增加拇指的速度都没有关系。
我该怎么做?
这是我的代码和一些注释:
import React, { Fragment } from 'react'
import './Filter.css'
const Filter = props => {
const sliderRef = React.useRef() // => main parent div
const initial_position = 0
const end_position = 200
const initial_min_value = 5 // => Initial price
const initial_max_value = 1290 // => Final price
let [thumb1_position, setValueThumb1] = React.useState(0)
let [thumb2_position, setValueThumb2] = React.useState(0)
let [min_value, setMinValue] = React.useState(initial_min_value)
let [max_value, setMaxValue] = React.useState(initial_max_value)
let [move, setMove] = React.useState(false) // => Enable thumbs to move
// Ensure that the thumb_2 will be in the end of the slider at first
React.useEffect(() => {
setValueThumb2(sliderRef.current.offsetWidth - 5)
}, [])
// Here I get the position of the cursor within the element (slider) and move the thumbs based on it.
const handleChange = e => {
let thumb_class = e.target.className
var rect = sliderRef.current.getBoundingClientRect();
const current_position = e.clientX - rect.left; // X position within the element.
// Only moves if 'move' is true
if (move === true) {
// Get the className to ensure that only the clicked thumb is moved
if (thumb_class.includes('left-thumb')) {
// Ensure that the thumb_1 will always be on the left and the thumb_2 on the right
// Ensure that neither of the thumbs exceed the limits of the slider
if (current_position >= initial_position && current_position < thumb2_position - 25) {
setValueThumb1(current_position)
} else if (current_position >= initial_position && current_position >= thumb2_position - 25) {
setValueThumb1(thumb2_position - 25)
setMove(false)
} else {
setValueThumb1(initial_position)
setMove(false)
}
if (thumb1_position - initial_position < 1) {
setMinValue(initial_min_value)
} else {
setMinValue((thumb1_position - initial_position) * 6.46)
}
} else if (thumb_class.includes('right-thumb')) {
if (current_position >= thumb1_position + 25 && current_position <= end_position) {
setValueThumb2(current_position)
} else if (current_position >= thumb1_position + 25 && current_position >= end_position) {
setValueThumb2(end_position)
setMove(false)
} else {
setValueThumb2(thumb1_position + 25)
setMove(false)
}
if (thumb2_position > end_position - 1) {
setMaxValue(initial_max_value)
} else {
setMaxValue((thumb2_position - initial_position) * 6.48)
}
}
}
}
const moveOn = e => {
setMove(true)
}
const moveOff = () => {
setMove(false)
}
return (
<Fragment>
<div>
<h6 style={{marginBottom: '35px'}}>PRICE FILTER</h6>
<div className="range-container"
onMouseMove={(e) => handleChange(e)}
onMouseDown={(e) => moveOn(e)}
onMouseUp={() => moveOff()}
onMouseLeave={() => moveOff()}
ref={sliderRef}
>
<div className="range">
<span className="rounded-circle left-thumb"
style={{
width:'15px',
height: '15px',
backgroundColor: 'red',
marginTop: '-6px',
marginLeft: thumb1_position - 7 + 'px'
}}
></span>
<span className="rounded-circle right-thumb"
style={{
width:'15px',
height: '15px',
backgroundColor: 'black',
marginTop: '-6px',
marginLeft: thumb2_position - 7 + 'px'
}}
></span>
<p style={{
marginLeft: thumb1_position - 15 + 'px',
position: 'absolute',
marginTop: '15px'}}
> {Math.floor(min_value)}
</p>
<p style={{
marginLeft: thumb2_position - 15 + 'px',
position: 'absolute',
marginTop: '15px'}}
> {Math.floor(max_value)}
</p>
</div>
</div>
</div>
</Fragment>
)
}
export default Filter
【问题讨论】:
-
很难从 gif 中分辨出来,但是当您朝任一方向移动时会发生这种情况吗?
-
@Ricardo Sanchez 是的,方向无关紧要。光标总是比拇指快
-
我明白了,如果您禁用 if (move === true) 语句,它的行为是否符合预期?
-
不,因为我需要确保拇指只能在事件
onMouseDown被触发时移动,如果onMouseUp被触发则意味着用户不再想要移动滑块,因此,move设置为false。如果没有这个条件,无论用户是否想要它都将始终启用。我认为的一种可能性是创建一个条件以确保在触发onMouseDown时光标不会离开拇指区域。但我只是想了想,我仍然不知道该怎么做。 -
有道理,我只是想缩小问题的范围
标签: javascript css reactjs animation dom