首页 > 解决方案 > 如何在最小值和最大值之间对齐范围滑块中的数据标签

问题描述

这是非常具体和随机的,我发现的答案不太适合这个特定的用例。为简洁起见,这里是 CodePen 演示的链接:

https://codepen.io/mikejandreau/pen/GRWNprN

正如您可能一眼看到的那样,我有四个数据标签在您移动时没有与范围滑块对齐。最小值和最大值都很好,这只是我遇到问题的中间值。

这是基于一个只有最小值/最大值的示例,我正在尝试对其进行调整。我尝试在data-min-label-id和之间添加额外的数据属性data-max-label-id,尽管效果不佳。

像往常一样,我可能遗漏了一些明显的东西。非常感谢任何帮助或指示。

<div id="wrapper">
  <div id="sliderContainer">

    <div class="tick-slider">

      <div class="tick-slider-header">
        <span><label for="weightSlider">Slider</label></span>
      </div>
      
      <div class="tick-slider-background"></div>
      <div id="weightProgress" class="tick-slider-progress"></div>
      <div id="weightTicks" class="tick-slider-tick-container"></div>
      <input
             id="weightSlider"
             class="tick-slider-input"
             type="range"
             min="0"
             max="5000"
             step="1000"
             value="1000"
             data-tick-step="1000"
             data-tick-id="weightTicks"
             data-value-id="weightValue"
             data-progress-id="weightProgress"
             data-handle-size="18"
             data-min-label-id="weightLabelMin"
             data-max-label-id="weightLabelMax"
             />

      <div class="tick-slider-value-container">
        <div id="weightLabelMin" class="tick-slider-label">0</div>

        <!-- I want to align these 4 items -->
        <div id="weightLabelA" class="tick-slider-label">1000</div>
        <div id="weightLabelB" class="tick-slider-label">2000</div>
        <div id="weightLabelC" class="tick-slider-label">3000</div>
        <div id="weightLabelD" class="tick-slider-label">4000</div> 

        <div id="weightLabelMax" class="tick-slider-label">5000</div>
        <div id="weightValue" class="tick-slider-value"></div>
      </div>
    </div>
  </div>
function init() {
    const sliders = document.getElementsByClassName("tick-slider-input");

    for (let slider of sliders) {
        slider.oninput = onSliderInput;
        updateValue(slider);
        updateValuePosition(slider);
        updateLabels(slider);
        updateProgress(slider);
        setTicks(slider);
    }
}

function onSliderInput(event) {
    updateValue(event.target);
    updateValuePosition(event.target);
    updateLabels(event.target);
    updateProgress(event.target);
}

function updateValue(slider) {
    let value = document.getElementById(slider.dataset.valueId);

    value.innerHTML = "<div>" + slider.value + "</div>";
}

function updateValuePosition(slider) {
    let value = document.getElementById(slider.dataset.valueId);

    const percent = getSliderPercent(slider);

    const sliderWidth = slider.getBoundingClientRect().width;
    const valueWidth = value.getBoundingClientRect().width;
    const handleSize = slider.dataset.handleSize;

    let left = percent * (sliderWidth - handleSize) + handleSize / 2 - valueWidth / 2;

    left = Math.min(left, sliderWidth - valueWidth);
    left = slider.value === slider.min ? 0 : left;

    value.style.left = left + "px";
}

function updateLabels(slider) {
    const value = document.getElementById(slider.dataset.valueId);
    const minLabel = document.getElementById(slider.dataset.minLabelId);
    const maxLabel = document.getElementById(slider.dataset.maxLabelId);

    const valueRect = value.getBoundingClientRect();
    const minLabelRect = minLabel.getBoundingClientRect();
    const maxLabelRect = maxLabel.getBoundingClientRect();

    const minLabelDelta = valueRect.left - (minLabelRect.left);
    const maxLabelDelta = maxLabelRect.left - valueRect.left;

    const deltaThreshold = 32;

    if (minLabelDelta < deltaThreshold) minLabel.classList.add("hidden");
    else minLabel.classList.remove("hidden");

    if (maxLabelDelta < deltaThreshold) maxLabel.classList.add("hidden");
    else maxLabel.classList.remove("hidden");
}

function updateProgress(slider) {
    let progress = document.getElementById(slider.dataset.progressId);
    const percent = getSliderPercent(slider);

    progress.style.width = percent * 100 + "%";
}

function getSliderPercent(slider) {
    const range = slider.max - slider.min;
    const absValue = slider.value - slider.min;

    return absValue / range;
}

function setTicks(slider) {
    let container = document.getElementById(slider.dataset.tickId);
    const spacing = parseFloat(slider.dataset.tickStep);
    const sliderRange = slider.max - slider.min;
    const tickCount = sliderRange / spacing + 1; // +1 to account for 0

    for (let ii = 0; ii < tickCount; ii++) {
        let tick = document.createElement("span");

        tick.className = "tick-slider-tick";

        container.appendChild(tick);
    }
}

function onResize() {
    const sliders = document.getElementsByClassName("tick-slider-input");

    for (let slider of sliders) {
        updateValuePosition(slider);
    }
}

window.onload = init;
window.addEventListener("resize", onResize);

标签: javascripthtmlcss

解决方案


推荐阅读