我正在尝试显示以拇指为中心的范围项目的值。通过读取值并将元素定位在范围元素上方作为其clientWidth
的百分比,这非常有效。
然而,偏离中间的偏差越来越大(见图片)导致价值不以拇指为中心。我确信这是因为拇指实际上移动的距离小于clientWidth
,因为拇指本身的大小可能会在轨道周围有一些空间。
如何将此考虑在内?
JSFiddle可以在这里找到:https://jsfiddle.net/jd4kncuk/
答案 0 :(得分:3)
使用CSS进行更多检查: link
var myRange = document.querySelector('#myRange');
var myValue = document.querySelector('#myValue');
var thumbWidth = 18;
var off = (myRange.clientWidth - thumbWidth) / (parseInt(myRange.max) - parseInt(myRange.min));
var px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) + (thumbWidth / 2);
myValue.style.left = px + 'px';
myValue.style.top = -myRange.offsetHeight - 5 + 'px';
myValue.innerHTML = myRange.value;
myRange.oninput = function() {
let px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) + (thumbWidth / 2);
myValue.innerHTML = myRange.value;
myValue.style.left = px + 'px';
};
<div style="position:relative; margin:auto; width:90%; margin-top:80px;">
<output style="position:absolute; min-width:100px; text-align: center;" id="myValue"></output>
<input type="range" id="myRange" min="0" max="200" step="5" style="width:80%" value="80">
</div>
答案 1 :(得分:2)
我想我已经解决了。该问题是由于未考虑拇指的宽度引起的。拇指不会在滑块上移动100%,而是100%-〜15px。这样,拇指永远不会与滑块的侧面重叠。请注意,滑块的〜15px宽度是从chrome获取的,在其他浏览器中,宽度可能有所不同。
要在定位值显示时考虑到这一点,我们需要将其偏移拇指宽度的一半,范围为+7.5像素至-7.5像素。这是一个更新的小提琴https://jsfiddle.net/crf96bw7/1/,显示了它的工作原理。我添加了一些额外的标记,以帮助显示值容器的中心位置。
var myRange = document.querySelector('#myRange');
var myValue = document.querySelector('#myValue');
var myValueInner = document.querySelector('#myValueInner');
var buttonWidth = 15;
var range = parseInt(myRange.max) - parseInt(myRange.min)
var centerDotOffset = (myRange.valueAsNumber / range - 0.5) * buttonWidth;
var off = myRange.clientWidth / range;
var px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) - centerDotOffset;
myValue.style.left = px + 'px';
myValue.style.top = -myRange.offsetHeight - 5 + 'px';
myValueInner.innerHTML = myRange.value;
myRange.oninput = function() {
var centerDotOffset = (myRange.valueAsNumber / range - 0.5) * buttonWidth
let px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) - centerDotOffset;
myValueInner.innerHTML = myRange.value;
myValue.style.left = px + 'px';
};
#container {
position: relative;
box-sizing: border-box;
margin: 0 auto;
width: 90%;
margin-top: 80px;
}
#myRange {
width: 100%;
margin: 0;
}
#myValue {
background: black;
}
#myValue #myValueInner {
width: 50%;
background: gold;
}
<div id="container">
<output style="position:absolute; min-width:100px; text-align: center;" id="myValue"><div id="myValueInner">
</div></output>
<input type="range" id="myRange" min="0" max="200" step="5" value="150">
</div>
答案 2 :(得分:2)
实际上,您可以style the track and the thumb使用CSS。然后,您具有已知的轨道和拇指宽度(否则,它们取决于平台),然后可以将其合并到计算中。
因此,我在示例中添加了简化的CSS,并将30px
的宽度放入thumbWidth
JS变量中,并更改了公式:
var myRange = document.querySelector('#myRange');
var myValue = document.querySelector('#myValue');
var thumbWidth = 30;
var off = (myRange.clientWidth - thumbWidth) / (parseInt(myRange.max) - parseInt(myRange.min));
var px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) + (thumbWidth / 2);
myValue.style.left = px + 'px';
myValue.style.top = -myRange.offsetHeight - 5 + 'px';
myValue.innerHTML = myRange.value;
myRange.oninput = function() {
let px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 2) + (thumbWidth / 2);
myValue.innerHTML = myRange.value;
myValue.style.left = px + 'px';
};
input[type=range] {
-webkit-appearance: none;
margin: 10px 0;
}
input[type=range]::-webkit-slider-runnable-track {
height: 10px;
background: gray;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 30px;
width: 30px;
background: crimson;
margin-top: -10px;
}
<div style="position:relative; margin:auto; width:90%; margin-top:80px;">
<output style="position:absolute; min-width:100px; text-align: center;" id="myValue"></output>
<input type="range" id="myRange" min="0" max="200" step="5" style="width:80%" value="80">
</div>
PS:一种更干净的方法是通过JS从<input type="range">
中读取拇指的宽度,这样就不需要自定义CSS。但是,reach it inside the user agent shadow dom似乎不可能。