问题描述
我正在尝试了解并修复双面输入滑块的错误
上面的滑块起始位置是 0,但由于光标移动不正确,我得到的值为 52。达到 0 后,我可以向左移动的值
SCSS:
$border-radius: 20px;
$primary: #709fdc;
$base: #071739;
$shadow-color: #274684;
$lighter-shadow: rgba($shadow-color,.2);
$white: #fff;
$gray: #8c8c8c;
$lighter-gray: rgba($gray,.1);
$time-line-width: 240px;
$transition: .3s all ease;
@mixin dragIndicator($property,$background,$z-index) {
#{$property}{
position: absolute;
top: 0;
z-index: $z-index;
width: 0;
height: 5px;
border-radius: 5px;
background: $background;
&:hover{
&::before{
opacity: 1;
}
&::after{
opacity: 1;
}
}
&::before{
opacity: 0;
content: attr(data-content);
display: block;
position: absolute;
top: -40px;
right: -23px;
width: 40px;
padding: 3px;
text-align: center;
color: white;
background: $shadow-color;
border-radius: $border-radius;
}
&::after{
opacity: 0;
content:'';
display: block;
position: absolute;
top: -18px;
right: -8px;
border-top: 8px solid $shadow-color;
border-left:8px solid transparent;
border-right:8px solid transparent;
}
#{$property}-drag{
position: absolute;
right: -7.5px;
top: -5px;
width: 15px;
height: 15px;
border-radius: 50%;
background: $base;
transition: all .3s;
&:hover{
Box-shadow: 0 0 0 6px $lighter-shadow;
}
}
}
}
body{
font-family: 'Rubik',sans-serif;
color: $base;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background: $lighter-gray;
.card{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 50px;
padding-top: 25px;
margin-top: 40px;
border-radius: $border-radius;
Box-shadow: 0px 0px 20px 0px $lighter-shadow;
background: $white;
overflow: hidden;
h2{
margin-bottom: 40px;
}
.current-value{
width: 100%;
label{
display: inline-flex;
width: 50px;
font-size: 20px;
}
input{
margin: 0;
max-width: 40px;
margin-bottom: 5px;
font-size: 16px;
color: white;
padding: 5px;
padding-left: 15px;
border: none;
border-radius: $border-radius;
background: $shadow-color;
}
}
.values{
display: flex;
justify-content: space-between;
font-weight: 600;
margin-top: 30px;
margin-bottom: 10px;
width: $time-line-width;
}
#slider{
position: relative;
margin: 0 auto;
width: $time-line-width;
height: 5px;
background: $primary;
border-radius: 5px;
cursor: pointer;
@include dragIndicator("#min",$primary,2);
@include dragIndicator("#max",$shadow-color,1);
}
}
}
.fa-instagram{
position: absolute;
color: $base;
top: 3%;
right: 2%;
font-size: 38px;
}
.fa-instagram:hover{
font-size: 42px;
color: $shadow-color;
transition: all .1s linear;
cursor: pointer;
}
input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
*:focus{
outline: none;
Box-shadow: 0 0 0 2px $primary;
}
反应代码:
class DoubleRangeSlider extends React.Component {
state = {
sliderWidth: 0,offsetSliderWidht: 0,min: 0,max: 200,minValueBetween: 10,currentMin: 55,inputMin: 55,currentMax: 100,inputMax: 100
};
componentDidMount() {
const { currentMin,currentMax,max } = this.state;
this.minValue.style.width = (currentMin*100)/max + "%";
this.maxValue.style.width = (currentMax*100)/max + "%";
this.setState({
sliderWidth: this.slider.offsetWidth,offsetSliderWidht: this.slider.offsetLeft,})
}
setMin = (e) => {
const { min,max,minValueBetween } = this.state;
const inputMin = e.target.value;
this.setState({
inputMin
});
if((inputMin >= min) && (inputMin <= (currentMax-minValueBetween))){
this.setState({
currentMin: parseInt(inputMin)
});
this.minValue.style.width = (inputMin*100)/max + "%";
}
}
changeMinValue = (e) => {
e.preventDefault();
document.addEventListener('mousemove',this.onMouseMoveMin);
document.addEventListener('mouseup',this.onmouseupMin);
document.addEventListener('touchmove',this.onMouseMoveMin);
document.addEventListener('touchend',this.onmouseupMin);
}
onMouseMoveMin = (e) => {
const { min,minValueBetween,sliderWidth,offsetSliderWidht } = this.state;
const dragedWidht = e.clientX - offsetSliderWidht;
const dragedWidhtInPercent = (dragedWidht*100)/sliderWidth;
const currentMin = Math.abs(parseInt((max * dragedWidhtInPercent)/100));
console.log(e.pageX,e.clientX,offsetSliderWidht);
console.log(currentMin,(currentMax-minValueBetween));
console.log((max * dragedWidhtInPercent)/100);
if( (currentMin >= min) && (currentMin <= (currentMax-minValueBetween))){
this.minValue.style.width = dragedWidhtInPercent + "%";
this.minValue.dataset.content = currentMin;
this.setState({
currentMin,inputMin: currentMin
})
}
}
onmouseupMin = () => {
document.removeEventListener('mouseup',this.onmouseupMin);
document.removeEventListener('mousemove',this.onMouseMoveMin);
document.removeEventListener('touchend',this.onMouseMoveMin);
document.removeEventListener('touchmove',this.onmouseupMin);
}
setMax = (e) => {
const { min,currentMin,minValueBetween } = this.state;
const inputMax = e.target.value;
this.setState({
inputMax
});
if((inputMax >= currentMin + minValueBetween) && (inputMax <= max)){
this.setState({
currentMax: parseInt(inputMax)
});
this.maxValue.style.width = (inputMax*100)/max + "%";
}
}
changeMaxValue = (e) => {
e.preventDefault();
document.addEventListener('mousemove',this.onMouseMoveMax);
document.addEventListener('mouseup',this.onmouseupMax);
document.addEventListener('touchmove',this.onMouseMoveMax);
document.addEventListener('touchend',this.onmouseupMax);
}
onMouseMoveMax = (e) => {
const { max,offsetSliderWidht} = this.state;
const maxWalueThumb = this.maxValue;
const dragedWidht = e.clientX - offsetSliderWidht;
const dragedWidhtInPercent = (dragedWidht*100)/sliderWidth;
const currentMax = Math.abs(parseInt((max * dragedWidhtInPercent)/100));
if( (currentMax >= (currentMin + minValueBetween)) && (currentMax <= max)){
maxWalueThumb.style.width = dragedWidhtInPercent + "%";
maxWalueThumb.dataset.content = currentMax;
this.setState({
currentMax,inputMax: currentMax
})
}
}
onmouseupMax = () => {
document.removeEventListener('mouseup',this.onmouseup);
document.removeEventListener('mousemove',this.onMouseMoveMax);
document.removeEventListener('touchend',this.onmouseup);
document.removeEventListener('touchmove',this.onMouseMoveMax);
}
maxForMin = () => {
const { currentMax,minValueBetween} = this.state;
return currentMax - minValueBetween;
}
minForMax = () => {
const { currentMin,minValueBetween} = this.state;
return currentMin + minValueBetween;
}
render() {
const { min,inputMin,inputMax,minValueBetween } = this.state;
return (
<div className="card">
<h2>Double range slider</h2>
<div className="current-value">
<label htmlFor="min-input">Min: </label>
<input
id="min-input"
type="number"
onChange={this.setMin}
value={inputMin}
min={min}
max={this.maxForMin}/>
<br/>
<label htmlFor="max-input">Max: </label>
<input
id="max-input"
type="number"
onChange={this.setMax}
value={inputMax}
min={this.minForMax}
max={max}/>
</div>
<div className="values">
<div>{ min }</div>
<div>{ max }</div>
</div>
<div ref={ref => this.slider = ref} id="slider">
<div ref={ref => this.minValue = ref} id="min" data-content={currentMin}>
<div ref={ref => this.minValueDrag = ref} id="min-drag" onMouseDown ={this.changeMinValue} onTouchStart={this.changeMinValue}></div>
</div>
<div ref={ref => this.maxValue = ref} id="max" data-content={currentMax}>
<div ref={ref => this.maxValueDrag = ref} id="max-drag" onMouseDown={this.changeMaxValue} onTouchStart={this.changeMaxValue}></div>
</div>
</div>
</div>
)
}
}
ReactDOM.render(
<DoubleRangeSlider/>,document.getElementById('root')
)
源代码:https://codepen.io/OlgaKoplik/pen/mdybLmE
解决方法
在 Stackoverflow 聊天社区问了同样的问题,其中一位成员帮我解决了上述问题。
问题:
const currentMin = Math.abs(parseInt((max * dragedWidhtInPercent)/100));
解决方案:他建议删除 currentMin const 中的 Math.abs()。删除后它工作正常,0后不动。
const currentMin = parseInt((max * dragedWidhtInPercent)/100);