gpt4 book ai didi

javascript - React 中的双面输入 slider

转载 作者:行者123 更新时间:2023-12-04 11:27:53 25 4
gpt4 key购买 nike

我在下面更新中链接的沙箱中有一个几乎可以工作的解决方案,你应该从这个开始。

我有一个不使用 React 创建的(单击“运行代码片段”)

var thumbsize = 14;

function draw(slider,splitvalue) {

/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var thumbsize = parseInt(slider.getAttribute('data-thumbsize'));
var rangewidth = parseInt(slider.getAttribute('data-rangewidth'));
var rangemin = parseInt(slider.getAttribute('data-rangemin'));
var rangemax = parseInt(slider.getAttribute('data-rangemax'));

/* set min and max attributes */
min.setAttribute('max',splitvalue);
max.setAttribute('min',splitvalue);

/* set css */
min.style.width = parseInt(thumbsize + ((splitvalue - rangemin)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
max.style.width = parseInt(thumbsize + ((rangemax - splitvalue)/(rangemax - rangemin))*(rangewidth - (2*thumbsize)))+'px';
min.style.left = '0px';
max.style.left = parseInt(min.style.width)+'px';

/* correct for 1 off at the end */
if(max.value>(rangemax - 1)) max.setAttribute('data-value',rangemax);

/* write value and labels */
max.value = max.getAttribute('data-value');
min.value = min.getAttribute('data-value');

}

function init(slider) {
/* set function vars */
var min = slider.querySelector('.min');
var max = slider.querySelector('.max');
var rangemin = parseInt(min.getAttribute('min'));
var rangemax = parseInt(max.getAttribute('max'));
var avgvalue = (rangemin + rangemax)/2;

/* set data-values */
min.setAttribute('data-value',rangemin);
max.setAttribute('data-value',rangemax);

/* set data vars */
slider.setAttribute('data-rangemin',rangemin);
slider.setAttribute('data-rangemax',rangemax);
slider.setAttribute('data-thumbsize',thumbsize);
slider.setAttribute('data-rangewidth',slider.offsetWidth);

/* draw */
draw(slider,avgvalue);

/* events */
min.addEventListener("input", function() {update(min);});
max.addEventListener("input", function() {update(max);});
}

function update(el){
/* set function vars */
var slider = el.parentElement;
var min = slider.querySelector('#min');
var max = slider.querySelector('#max');
var minvalue = Math.floor(min.value);
var maxvalue = Math.floor(max.value);

/* set inactive values before draw */
min.setAttribute('data-value',minvalue);
max.setAttribute('data-value',maxvalue);

var avgvalue = (minvalue + maxvalue)/2;

/* draw */
draw(slider,avgvalue);
}

var sliders = document.querySelectorAll('.min-max-slider');
sliders.forEach( function(slider) {
init(slider);
});
.min-max-slider {
position: relative;
width: 200px;
text-align: center;
margin-bottom: 50px;
}

.min-max-slider > label {
display: none;
}

.min-max-slider > input {
cursor: pointer;
position: absolute;
}


/* webkit specific styling */
.min-max-slider > input {
-webkit-appearance: none;
outline: none!important;
background: transparent;
background-image: linear-gradient(to bottom, transparent 0%, transparent 30%, silver 30%, silver 60%, transparent 60%, transparent 100%);
}

.min-max-slider > input::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 14px; /* Set a specific slider handle width */
height: 14px; /* Slider handle height */
background: #eee; /* Green background */
cursor: pointer; /* Cursor on hover */
border: 1px solid gray;
border-radius: 100%;
}

.min-max-slider > input::-webkit-slider-runnable-track {cursor: pointer;}
<div class="min-max-slider" data-legendnum="2">
<label for="min">Minimum price</label>
<input id="min" class="min" name="min" type="range" step="1" min="0" max="3000" />
<label for="max">Maximum price</label>
<input id="max" class="max" name="max" type="range" step="1" min="0" max="3000" />
</div>

我尝试使用 React 创建相同类型的组件。但是每个拇指 handle 只能滑动到中间点,与非 react 示例一样,较小的 slider 根本不能高于较高的 slider ,反之亦然。
我还想要一些方法使超出拇指 handle 范围的 slider 颜色更深。

var thumbsize = 14;

const Slider = ({min, max}) => {
const avg = (min + max)/2;
const width = 300
const minWidth = thumbsize + ((avg - min)/(max - min))*(width - (2*thumbsize))
const styles={
min:{
width: minWidth,
left: 0
},
max:{
width: thumbsize + ((max - avg)/(max - min))*(width - (2*thumbsize)),
left: minWidth
}
}

return (
<div
class="min-max-slider"
data-legendnum="2"
data-rangemin={min}
data-rangemax={max}
data-thumbsize={thumbsize}
data-rangewidth={width}
>
<label htmlFor="min">Minimum price</label>
<input
id="min"
className="min"
style={styles.min}
name="min"
type="range"
step="1"
min={min}
max={avg}
data-value={min}
/>
<label htmlFor="max">Maximum price</label>
<input
id="max"
className="max"
style={styles.max}
name="max"
type="range"
step="1"
min={avg}
max={max}
data-value={max}
/>
</div>
)
}

ReactDOM.render(<Slider min={300} max={3000} />, document.querySelector("#root"))
 



.min-max-slider {
position: relative;
width: 200px;
text-align: center;
margin-bottom: 50px;
}

.min-max-slider > label {
display: none;
}

.min-max-slider > input {
cursor: pointer;
position: absolute;
}


/* webkit specific styling */
.min-max-slider > input {
-webkit-appearance: none;
outline: none!important;
background: transparent;
background-image: linear-gradient(to bottom, transparent 0%, transparent 30%, silver 30%, silver 60%, transparent 60%, transparent 100%);
}

.min-max-slider > input::-webkit-slider-thumb {
-webkit-appearance: none; /* Override default look */
appearance: none;
width: 14px; /* Set a specific slider handle width */
height: 14px; /* Slider handle height */
background: #eee; /* Green background */
cursor: pointer; /* Cursor on hover */
border: 1px solid gray;
border-radius: 100%;
}

.min-max-slider > input::-webkit-slider-runnable-track {cursor: pointer;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>


更新
使用下面lissetdm的解决方案,我已经能够创建一个双面 slider ,您可以在 this sandbox上查看。 ,但它仍然存在一些问题。
  • 橙色看起来并不总是与灰色重叠

  • enter image description here
    有时,出乎意料的是,这种差异非常明显
    enter image description here
    enter image description here
  • 当两个拇指 block 都被拖到边缘时,一个将另一个向下推

  • enter image description here
  • 我似乎无法删除这个轮廓,它并不总是出现

  • enter image description here

    我在 中对此进行了测试火狐

    最佳答案

    随着 react 的工作,您需要将 avg 移动到组件的状态,并在输入 onChange 事件期间更新它的值:

    const Slider = ({ min, max }) => {
    const [avg, setAvg] = useState((min + max) / 2);
    const [minVal, setMinVal] = useState(avg);
    const [maxVal, setMaxVal] = useState(avg);

    const width = 300;
    const minWidth =
    thumbsize + ((avg - min) / (max - min)) * (width - 2 * thumbsize);
    const styles = {
    min: {
    width: minWidth,
    left: 0
    },
    max: {
    width: thumbsize + ((max - avg) / (max - min)) * (width - 2 * thumbsize),
    left: minWidth
    }
    };

    useEffect(() => {
    setAvg((maxVal + minVal) / 2);
    }, [minVal, maxVal]);


    return (
    <div
    className="min-max-slider"
    data-legendnum="2"
    data-rangemin={min}
    data-rangemax={max}
    data-thumbsize={thumbsize}
    data-rangewidth={width}
    >
    <label htmlFor="min">Minimum price</label>
    <input
    id="min"
    className="min"
    style={styles.min}
    name="min"
    type="range"
    step="1"
    min={min}
    max={avg}
    value={minVal}
    onChange={({ target }) => setMinVal(Number(target.value))}
    />
    <label htmlFor="max">Maximum price</label>
    <input
    id="max"
    className="max"
    style={styles.max}
    name="max"
    type="range"
    step="1"
    min={avg}
    max={max}
    value={maxVal}
    onChange={({ target }) => setMaxVal(Number(target.value))}
    />
    </div>
    );
    };
    更新

    I can't seem to remove this outline, which doesn't always appear


    出现此行是因为浏览器检测到输入无效。要禁用此效果,请使用:
    input[type="range"]:invalid {
    box-shadow: none;
    }

    The orange doesn't always look like it overlaps the gray



    When both thumb pieces are dragged to the edges, the one pushes theother down


    我无法重现这种情况,但我建议您使用最小和最大位置控制背景颜色:
    CSS:
    input[type="range"] {
    --minRangePercent: 0%;
    --maxRangePercent: 0%;
    height: .4rem;
    }

    .min-max-slider > input.min {
    background-image: linear-gradient(
    to right,
    silver 0%,
    silver var(--minRangePercent),
    orange var(--minRangePercent),
    orange 100%
    );
    }

    .min-max-slider > input.max {
    background-image: linear-gradient(
    to right,
    orange 0%,
    orange var(--maxRangePercent),
    silver var(--maxRangePercent),
    silver 100%
    );
    }
    JS:
    const minPercent = ((minVal - min) / (avg - min)) * 100;
    const maxPercent = ((maxVal - avg) / (max - avg)) * 100;
    const styles = {
    min: {
    width: minWidth,
    left: 0,
    "--minRangePercent": `${minPercent}%`
    },
    max: {
    width: thumbsize + ((max - avg) / (max - min)) * (width - 2 * thumbsize),
    left: minWidth,
    "--maxRangePercent": `${maxPercent}%`
    }
    };
    Working example

    关于javascript - React 中的双面输入 slider ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65095361/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com