如何让指针指向滑块拇指的中心? CSS 和 Jquery

how to get a pointer pointing at centre of slider thumb? CSS and Jquery

我有一个功能可以显示价格范围和最重复的价格(模式)。我所做的是我使用了范围输入类型并将其停用(因此它不能被用户移动,因为它仅用于说明)。

下面是我的 HTML、CSS 和 JS,我想这会更好地解释我的问题

<div class="range">
    <div class="sliderValue">
        <span class="show" style="left: ${pinPostion}%;">${mostCommonMaxPrice}</span>
    </div>
    <div class="field">
        <div class="value left">${lowestMinPrice}</div>
        <input type="range" min="${lowestMinPrice}" max="${highestMaxPrice}" value="${mostCommonMaxPrice}" disabled>
        <div class="value right">${highestMaxPrice}</div>
    </div>
</div>
.range{
  height: 40px;
  width: 130px;
  background: #fff;
  border-radius: 10px;
  padding: 0 32.5px 0 22.5px;
}
.field{
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  position: relative;
}
.field .value{
  position: absolute;
  font-size: 12px;
  color: #4638D2;
  font-weight: 600;
}
.field .value.left{
  left: -15px;
}
.field .value.right{
  right: -21.5px;
}
.range input{
  -webkit-appearance: none;
  width: 100%;
  height: 3px;
  background: #ddd;
  border-radius: 5px;
  outline: none;
  border: none;
  z-index: 2222;
}
.range input::-webkit-slider-thumb{
  -webkit-appearance: none;
  width: 10px;
  height: 10px;
  background: #4638D2 !important;
  border-radius: 50%;
  background: #4638D2;
  border: 1px solid #4638D2;
}
 
.range input::-moz-range-progress{
  background: #4638D2;
}
.sliderValue{
  position: relative;
  width: 100%;
  align-items: center;
}
.sliderValue span{
  font-size: 8px;
  position: absolute;
  height: 22.5px;
  width: 22.5px;
  /*transform: translateX(-70%) scale(0);*/
  font-weight: 600;
  top: -15px;
  line-height: 27.5px;
  z-index: 2;
  color: #fff;
  text-align: center;
}
.sliderValue span.show{
  transform: translateX(-70%) scale(1.3);
}
.sliderValue span:after{
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  background: #4638D2;
  border: 3px solid #fff;
  z-index: -1;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  border-bottom-left-radius: 50%;
  box-shadow: 0px 0px 8px rgba(0,0,0,0.1);
  border-top-left-radius: 50%;
  border-top-right-radius: 50%;
}
const pinPostion = (((mostCommonMaxPrice - lowestMinPrice)/(highestMaxPrice - lowestMinPrice)) * 100) + lowestMinPrice;

正如您在图片中看到的,我无法让显示模式编号的气泡指向滑块拇指位置,它仅在 100 时显示良好,但如果大于或小于,则它会离开位置,我试图计算百分比并将其作为变量传递,但它仍然存在,我不确定我的 CSS 是否错误,或者它是正在使用的方程式还是我做的所有这些都是错误的并且有一个更简单的方法来做到这一点。非常感谢你的帮助。如果您提出问题,我们将不胜感激:)

我在这里找到了一些代码示例,它使用类似于您的方法手动计算价值气泡的位置,试试看:

const allRanges = document.querySelectorAll(".range-wrap");
allRanges.forEach(wrap => {
  const range = wrap.querySelector(".range");
  const bubble = wrap.querySelector(".bubble");

  range.addEventListener("input", () => {
    setBubble(range, bubble);
  });
  setBubble(range, bubble);
});

function setBubble(range, bubble) {
  const val = range.value;
  const min = range.min ? range.min : 0;
  const max = range.max ? range.max : 100;
  const newVal = Number(((val - min) * 100) / (max - min));
  bubble.innerHTML = val;

  // Sorta magic numbers based on size of the native UI thumb
  bubble.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
}
.range-wrap {
  position: relative;
  margin: 0 auto 3rem;
}
.range {
  width: 100%;
}
.bubble {
  background: red;
  color: white;
  padding: 4px 12px;
  position: absolute;
  border-radius: 4px;
  left: 50%;
  transform: translateX(-50%);
}
.bubble::after {
  content: "";
  position: absolute;
  width: 2px;
  height: 2px;
  background: red;
  top: -1px;
  left: 50%;
}

body {
  margin: 2rem;
}
<div class="range-wrap">
  <input type="range" class="range">
  <output class="bubble"></output>
</div>

<div class="range-wrap">
  <input type="range" class="range" min="20" max="940">
  <output class="bubble"></output>
</div>

<div class="range-wrap" style="width: 75%;">
  <input type="range" class="range" min="50" max="60" step="2">
  <output class="bubble"></output>
</div>

<div class="range-wrap" style="width: 55%;">
  <input type="range" class="range" min="-20" max="20">
  <output class="bubble"></output>
</div>

我在这里找到了https://css-tricks.com/value-bubbles-for-range-inputs/

我认为针点位置没有考虑针点本身的边框宽度,因此它没有与其尖端的中心对齐。

考虑这个例子,精确点应该在中间:

variable value
lowestMinPrice 0
highestMaxPrice 100
mostCommonMaxPrice 50
const pinPostion = (((mostCommonMaxPrice - lowestMinPrice)/(highestMaxPrice - lowestMinPrice)) * 100) + lowestMinPrice;
pinPostion = (((50 - 0)/(100 - 0)) * 100) + 0;
pinPostion = 50

精确点是由具有边框半径的旋转元素制成的。如果我去掉半径,这就是它的样子

如果我进一步取消转换,这就是它的样子

即使我将数字移植到您的示例中,精确度也有一点偏差。

.range {
  height: 40px;
  width: 130px;
  background: #fff;
  border-radius: 10px;
  padding: 0 32.5px 0 22.5px;
}

.field {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  position: relative;
}

.field .value {
  position: absolute;
  font-size: 12px;
  color: #4638D2;
  font-weight: 600;
}

.field .value.left {
  left: -15px;
}

.field .value.right {
  right: -21.5px;
}

.range input {
  -webkit-appearance: none;
  width: 100%;
  height: 3px;
  background: #ddd;
  border-radius: 5px;
  outline: none;
  border: none;
  z-index: 2222;
}

.range input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 10px;
  height: 10px;
  background: #4638D2 !important;
  border-radius: 50%;
  background: #4638D2;
  border: 1px solid #4638D2;
}

.range input::-moz-range-progress {
  background: #4638D2;
}

.sliderValue {
  position: relative;
  width: 100%;
  align-items: center;
}

.sliderValue span {
  font-size: 8px;
  position: absolute;
  height: 22.5px;
  width: 22.5px;
  /*transform: translateX(-70%) scale(0);*/
  font-weight: 600;
  top: -15px;
  line-height: 27.5px;
  z-index: 2;
  color: #fff;
  text-align: center;
}

.sliderValue span.show {
  transform: translateX(-70%) scale(1.3);
}

.sliderValue span:after {
  position: absolute;
  content: '';
  height: 100%;
  width: 100%;
  background: #4638D2;
  border: 3px solid #fff;
  z-index: -1;
  left: 50%;
  transform: translateX(-50%) rotate(45deg);
  border-bottom-left-radius: 50%;
  box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);
  border-top-left-radius: 50%;
  border-top-right-radius: 50%;
}
<div class="range">
  <div class="sliderValue">
    <span class="show" style="left: 50%;">50</span>
  </div>
  <div class="field">
    <div class="value left">0</div>
    <input type="range" min="0" max="100" value="50" disabled>
    <div class="value right">100</div>
  </div>
</div>