css 确定范围输入上“拇指”的移动范围

ufj5ltwl  于 2023-04-08  发布在  其他
关注(0)|答案(3)|浏览(219)

我试图显示一个范围项的值,该值位于拇指上方的中心位置。通过阅读值并将该元素定位在范围元素上方作为其clientWidth的百分比,效果非常好。
然而,距离中间的偏移量越来越大(见图片),这导致值不在拇指的中心。我确信这是因为拇指实际上移动的距离小于clientWidth,因为拇指本身的大小以及轨道周围的一些空间。
我该如何考虑这一点?

JSFiddle可以在这里找到:https://jsfiddle.net/jd4kncuk/

var myRange = document.querySelector('#myRange');
var myValue = document.querySelector('#myValue');

var off = myRange.clientWidth / (parseInt(myRange.max) - parseInt(myRange.min));
var px = ((myRange.valueAsNumber - parseInt(myRange.min)) * off) - (myValue.clientWidth / 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);
  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>
uqjltbpv

uqjltbpv1#

使用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>
ctehm74n

ctehm74n2#

我想我已经解决了这个问题。这个问题是由于没有考虑到滑块的宽度而引起的。滑块并没有100%地移动,而是100% - ~ 15 px。这样滑块就不会与滑块的两侧重叠。请注意,滑块滑块滑块的~ 15 px宽度来自chrome,在其他浏览器中可能会有所不同。
为了在定位值显示时考虑到这一点,我们需要将其偏移拇指宽度的一半的百分比,范围从+7.5px到-7.5px。这里是一个更新的fiddle 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>
cbwuti44

cbwuti443#

实际上,你可以用CSS对范围进行style the track and the thumb。然后你就有了一个已知的轨道和拇指的宽度(否则它们是依赖于平台的),然后你可以将其纳入计算。
因此,我在示例中添加了简化的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 inside the user agent shadow dom是不可能的。

相关问题