在自定义范围滑块中捕捉刻度并移动刻度位置



我是很新的,我正试图找出如何解决我的问题。我试图设计一个范围滑块来控制机器应用程序的速度。我已经在这里搜索了好几个小时了,但我找不到我的问题的正确结果。我在这里添加的代码是我发现其他页面的东西,所以它可能不是最好的解决方案。

我想用它做三件不同的事情作为开始。

  1. 第一个问题是,我想把句柄捕捉到我所做的滴答,是否有可能用代码做到这一点,所以如果我改变我的滴答,句柄仍然会捕捉到新的滴答?
  2. 是否有可能在0和10%之间有更多的刻度,所以我有2%的步长到10%,当手柄在那里时,它会捕捉到2%的步长,当它超过10%时,它会捕捉到另一个10%的步长间隔。
  3. 是否有可能在滑动条内移动刻度,而在中间有标签?我想在底部和顶部都打勾,然后在中间打标签。我附上了一张我想要的照片。

多谢

范围滑块的想法!

链接到我的代码

https://www.w3schools.com/code/tryit.asp?filename=GT1V8EFG2RUA

function toggleStep(element) {
if (element.value >= 10) { element.step = 10; }
else { element.step = 2; }
}
/**
* Sniffs for Older Edge or IE,
* more info here:
* https://stackoverflow.com/q/31721250/3528132
*/
function isOlderEdgeOrIE() {
return (
window.navigator.userAgent.indexOf("MSIE ") > -1 ||
!!navigator.userAgent.match(/Trident.*rv:11./) ||
window.navigator.userAgent.indexOf("Edge") > -1
);
}
function valueTotalRatio(value, min, max) {
return ((value - min) / (max - min)).toFixed(2);
}
function getLinearGradientCSS(ratio, leftColor, rightColor) {
return [
'-webkit-gradient(',
'linear, ',
'left top, ',
'right top, ',
'color-stop(' + ratio + ', ' + leftColor + '), ',
'color-stop(' + ratio + ', ' + rightColor + ')',
')'
].join('');
}
function updateRangeEl(rangeEl) {
var ratio = valueTotalRatio(rangeEl.value, rangeEl.min, rangeEl.max);
rangeEl.style.backgroundImage = getLinearGradientCSS(ratio, '#00FF00', '#c5c5c5');
}
function initRangeEl() {
var rangeEl = document.querySelector('input[type=range]');
var textEl = document.querySelector('input[type=text]');
/**
* IE/Older Edge FIX
* On IE/Older Edge the height of the <input type="range" />
* is the whole element as oposed to Chrome/Moz
* where the height is applied to the track.
*
*/
if (isOlderEdgeOrIE()) {
rangeEl.style.height = "20px";
// IE 11/10 fires change instead of input
// https://stackoverflow.com/a/50887531/3528132
rangeEl.addEventListener("change", function(e) {
textEl.value = e.target.value;
});
rangeEl.addEventListener("input", function(e) {
textEl.value = e.target.value;
});
} else {
updateRangeEl(rangeEl);
rangeEl.addEventListener("input", function(e) {
updateRangeEl(e.target);
textEl.value = e.target.value;
});
}
}
initRangeEl();
.slidecontainer {
width: 500px;
margin-left:15px;
}
input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
width:100%;
height: 50px;
padding: 0;
border: solid 2px #000000;
border-radius: 8px;
outline: none;
cursor: pointer;
}
datalist {
display: flex;
margin-left: 2px;
margin-top: -50px;
}
datalist option {
flex-basis: 10%;
border-left: 1px solid #000;
}
datalist option:nth-child(-n+5) {
flex-basis: 2%;
}
datalist option:last-child {
display: none;
}
/*Chrome thumb*/
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-border-radius: 5px;
/*16x16px adjusted to be same as 14x14px on moz*/
height: 45px;
width: 45px;
border-radius: 5px;
background: #e7e7e7;
border: 2px solid #000000;
opacity: 0.4;
cursor: pointer;
border-radius: 8px; 
}

/*Mozilla thumb*/
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-moz-border-radius: 5px;
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}

/*IE & Edge input*/
input[type=range]::-ms-track {
width: 300px;
height: 6px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 2px 0;
/*remove default tick marks*/
color: transparent;
margin-left:15px;
}

/*IE & Edge thumb*/
input[type=range]::-ms-thumb {
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}

/*IE & Edge left side*/
input[type=range]::-ms-fill-lower {
background: #000000;
border-radius: 2px;
margin-left:15px;
}

/*IE & Edge right side*/
input[type=range]::-ms-fill-upper {
background: #000000;
border-radius: 2px;
}

/*IE disable tooltip*/
input[type=range]::-ms-tooltip {
display: none;
}
input[type="text"] {
border: none;
}

.sliderticks {
display: flex;
justify-content: space-between;
padding: 0 50px;
}
.sliderticks p {
position: relative;
display: flex;
justify-content: center;
text-align: center;
width: 1px;
background: #D3D3D3;
height: 10px;
line-height: 40px;
margin: 0 0 20px 0;
}
<h1>Custom Range Slider</h1>
<p>Drag the slider to display the current value.</p>
<div class="slidecontainer">
<input type="range" value="10" min="0" max="100" oninput="toggleStep(this)" list="sliderticks"   />
<div class="datalist">
<datalist id="sliderticks">
<option>0</option>
<option>2</option>
<option>4</option>
<option>6</option>
<option>8</option>
<option>10</option>
<option>20</option>
<option>30</option>
<option>40</option>
<option>50</option>
<option>60</option>
<option>70</option>
<option>80</option>
<option>90</option>
<option>100</option>
</datalist>
</div>
</div>

希望下面的代码能满足您的需求:

document.querySelectorAll('.range input[type="range"]').forEach((range) => {
range.tickmarks = [...range.list.options].map((el) => parseFloat(el.value));
range.list.insertAdjacentHTML('afterend', `<div class="range-value"></div>`);
range.max = parseFloat(range.tickmarks[range.tickmarks.length - 1]);
let q = (range.clientWidth - 40) / range.max;
range.addEventListener('input', function(ev) {
if (this.hasAttribute('ticks-only')) {
this.value = range.tickmarks.map((x) => x).sort((x, y) => Math.abs(x - this.value) - Math.abs(y - this.value))[0];
}
this.parentElement.style.backgroundSize = `${(this.value * range.clientWidth) / range.max}px 100%, 100% 100%`;
this.list.nextElementSibling.textContent = this.value;
this.list.nextElementSibling.style.left = `${20 + this.value * q}px`;
});
range.tickmarks.forEach((el, i) => {
range.list.options[i].label = el % 10 ? ' ' : el;
range.list.options[i].style.left = 20 + el * q + 'px';
});
range.dispatchEvent(new Event('input', {bubbles: true}));
});
.range {
position: relative;
height: 52px; width: 500px;
border-radius: 0.125em;
overflow: hidden;
font: 16px/1em sans-serif;
background-image: linear-gradient(to right, #7bad23, #39594c), linear-gradient(to bottom, #84929d, #46576d);
background-size: 0 100%, 100% 100%;
background-repeat: no-repeat;
box-shadow: 0 0 0 0.125em #7f8c97, 0.0625em 0.125em 0.3125em 0em #93a2bd, -0.125em -0.1875em 0.3125em 0em #0e1116, inset 0 0 1.25em -0.3125em #0e1116;
}
datalist {
position: relative;
display: block;
height: 100%; width: 100%;
pointer-events: none;
}
.range datalist option {
position: absolute !important;
display: grid;
place-items: center;
height: 100%;
padding: 0;
transform: translatex(-50%);
font: bold 12px/1em monospace !important;
text-shadow: 1px 0 0.16666667em #fff5;
}
.range datalist option::before,
.range datalist option::after {
content: "";
position: absolute;
left: 50%;
height: 100%; width: 0;
box-shadow: 0 0 0 0.08333333em #0008;
}
.range datalist option::before { bottom: calc(50% + 1em); }
.range datalist option::after { top: calc(50% + 1em); }
input[type="range"] {
appearance: none;
position: absolute;
top: 0; left: 0; z-index: 1;
margin: 0;
height: 100%; width: 100%;
box-sizing: border-box;
font: inherit;
background-color: transparent;
cursor: pointer;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none;
display: block;
width: 2.5em; height: 2.5em;
border: none;
border-radius: 0.75em;
background-color: #99c7;
box-shadow: 0 0 0.125em 0 #282850dd, inset 0 0 0.125em 0.125em #282850dd;
transition: background-color 0.5s ease-out 0.5s;
}
input[type="range"]:active::-webkit-slider-thumb {
background-color: #fff8;
transition: background-color 0.5s ease-out;
}
.range-value {
position: absolute;
top: 0; left: 0; z-index: 2;
display: grid;
place-items: center;
height: 100%;
transform: translatex(-50%);
font: bold 12px/1em monospace !important;
text-shadow: 0 0 0.16666667em #fff;
opacity: 0;
pointer-events: none;
transition: opacity 1s ease-in;
}
input[type="range"]:focus-visible~.range-value,
input[type="range"]:active~.range-value,
input[type="range"]:hover~.range-value {
opacity: 1;
transition: opacity 0.5s ease-out;
}
body { margin: 0; height: 100vh; background-color: #42516c; display: flex; flex-flow: column nowrap; justify-content: center; align-items: center; }
<div class="range">
<input type="range" list="high">
<datalist id="high">
<option value="0">
<option value="2">
<option value="4">
<option value="6">
<option value="8">
<option value="10">
<option value="20">
<option value="30">
<option value="40">
<option value="50">
<option value="60">
<option value="70">
<option value="100">
</datalist>
</div>
<h3>With "ticks-only" attribute</h3>
<div class="range">
<input type="range" list="bass" ticks-only>
<datalist id="bass">
<option value="0">
<option value="10">
<option value="15">
<option value="20">
<option value="30">
<option value="40">
<option value="50">
<option value="60">
<option value="70">
<option value="72">
<option value="74">
<option value="76">
<option value="78">
<option value="80">
<option value="100">
<option value="175">
<option value="200">
</datalist>
</div>

注意!此代码仅适用于webkit。(在Chrome中测试)。Firefox无法正常使用"position"属性,当父元素和子元素设置为"absolute"

最新更新