在 HTML 范围滑块中的步骤下准确定位标签

问题描述 投票:0回答:1

我正在努力创建这个: enter image description here

它必须支持沿着滑块的非线性标签,例如400K、500K、750K、1M,但视觉上间隔均匀。

我已经接近这个目标,但我无法按预期将中间的标签放入空格中。 当有 3 个选项时,中间标签位置正确,但当有 4 个或更多步骤时,中间标签与点不对齐。

    <div id="sliders-container">
      <div id="slider1" class="slider-container" data-title="With 5 options" data-values='{"$500":500,"$1,000":1000,"$2,500":2500,"$5,000":5000,"$10,000":10000}' data-start-value="5000"></div>


      <div id="slider3" class="slider-container" data-title="With 3 options" data-values='{"$50K":50000,"$100K":100000,"$200K":200000}' data-start-value="100000"></div>

      <div id="slider2" class="slider-container" data-title="With 4 options" data-values='{"$50K":50000,"$100K":100000,"$200K":200000, "$1M":1000000}' data-start-value="50000"></div>

    </div>
    
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

    <style>
      .slider-container {
        max-width: 480px;
        margin: 50px auto;
        position: relative;
      }

      .slider {
        z-index: 1;
        position: relative;
      }

      .slider-dots {
        top: 6px;
        margin-left: auto;
        margin-right: auto;
        position: absolute;
        width: 100%;
        display: flex;
        justify-content: space-between;
        pointer-events: none;
        z-index: 0;
      }

      .slider-dots div {
        background-color: #cbcbcb;
        width: 12px;
        height: 12px;
        border-radius: 50%;
      }

      .form-range::-webkit-slider-runnable-track {
        background: #cbcbcb;
        height: 2px;
      }

      .form-range::-webkit-slider-thumb {
        width: 1.5rem;
        height: 1.5rem;
        cursor: pointer;
        -webkit-appearance: none;
        appearance: none;
        border-radius: 50%;
        border: 2px solid purple;
        box-shadow: inset 0px 0px 0px 2px white;
        background-color: purple;
        margin-top: -0.75rem;
      }

      .dynamic-slider-values span {
        flex-basis: 100%;
        text-align: center;
      }

      .dynamic-slider-values span:first-of-type {
        text-align: left;
      }

      .dynamic-slider-values span:last-of-type {
        text-align: right;
      }

    </style>


    <script>
      function createSliderContainer(sliderData) {
        const container = document.createElement('div');
        container.classList.add('slider-container');

        container.innerHTML = `
        <b>${sliderData.title}</b>
        <div class="row">
          <div class="col-8 col-sm-9">
            <div style="position: relative;">
              <input type="range" min="1" max="1" value="1" class="form-range slider dynamic-slider">
              <div class="slider-dots dynamic-slider-dots"></div>
              <div class="d-flex justify-content-between small dynamic-slider-values"></div>
            </div>
          </div>
          <div class="col-4 col-sm-3">
            <select class="form-select dynamic-value-select"></select>
          </div>
        </div>
      `;

        return container;
      }

      function initializeSlider(sliderContainer, keyValuePairs, startValue) {
        const slider = sliderContainer.querySelector('.dynamic-slider');
        const sliderDots = sliderContainer.querySelector('.dynamic-slider-dots');
        const sliderValues = sliderContainer.querySelector('.dynamic-slider-values');
        const valueSelect = sliderContainer.querySelector('.dynamic-value-select');

        const keys = Object.keys(keyValuePairs); // Extract the labels
        const values = Object.values(keyValuePairs); // Extract the actual values

        // Update the slider max attribute based on the number of values
        slider.max = keys.length;

        // Initialize the select dropdown
        valueSelect.innerHTML = '';
        keys.forEach((key, index) => {
          const option = document.createElement('option');
          option.value = values[index];
          option.textContent = key;
          valueSelect.appendChild(option);
        });

        // Set the start value for the slider and select dropdown
        const startIndex = values.indexOf(startValue);
        if (startIndex !== -1) {
          slider.value = startIndex + 1;
          valueSelect.value = values[startIndex];
        } else {
          slider.value = 1; // Default to the first value if startValue is not found
          valueSelect.value = values[0];
        }

        // Create dots and value labels
        sliderDots.innerHTML = '';
        sliderValues.innerHTML = '';

        keys.forEach((key, index) => {
          // Create dots
          const dot = document.createElement('div');
          sliderDots.appendChild(dot);

          // Create value labels
          const valueLabel = document.createElement('span');
          valueLabel.textContent = key;
          sliderValues.appendChild(valueLabel);
        });

        // Sync slider with select dropdown
        slider.oninput = function() {
          valueSelect.value = values[this.value - 1];
        };

        // Sync select dropdown with slider
        valueSelect.onchange = function() {
          slider.value = values.indexOf(parseInt(this.value)) + 1;
        };
      }

      function createSliders() {
        const sliders = document.querySelectorAll('.slider-container');

        sliders.forEach(slider => {
          const title = slider.getAttribute('data-title');
          const keyValuePairs = JSON.parse(slider.getAttribute('data-values'));
          const startValue = parseInt(slider.getAttribute('data-start-value'), 10);

          const sliderContainer = createSliderContainer({
            title
          });
          slider.appendChild(sliderContainer);
          initializeSlider(sliderContainer, keyValuePairs, startValue);
        });
      }

      // Initialize sliders based on the HTML data attributes
      createSliders();

    </script>

html css slider
1个回答
0
投票

将标签贴在点上的建议有效。 这是完成的版本:

<html>


<body>
    <div class="container mt-5">
      <div class="comborange-init mb-5" data-values='{"$50K":50000,"$100K":100000,"$200K":200000}' data-start-value="100000"></div>

      <div class="comborange-init mb-5" data-values='{"$50K":50000,"$100K":100000,"$200K":200000, "$1M":1000000}' data-start-value="50000"></div>

      <div class="comborange-init mb-5" data-values='{"$500":500,"$1,000":1000,"$2,500":2500,"$5,000":5000,"$10,000":10000}' data-start-value="5000"></div>
    
    </div>


    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

    <style>




       .comborange-inner-container {
        position: relative;
        height: 50px;
      }

       .form-range {
        z-index: 1;
        position: relative;
      }

       .comborange-dots {
        z-index: 0;
        top: 6px;
        margin-left: auto;
        margin-right: auto;
        position: absolute;
        width: 100%;
        display: flex;
        justify-content: space-between;
        pointer-events: none;
      }

       .comborange-dots div {
        background-color: #cbcbcb;
        width: 12px;
        height: 12px;
        border-radius: 50%;
        position: relative;
      }

       .comborange-dots div span {
        position: absolute;
        width: 100px;
        word-break: keep-all;
        text-align: center;
        left: -44px;
        top: 16px;
      }

       .comborange-dots div:first-of-type span {
        text-align: left;
        left: 0px;
      }

       .comborange-dots div:last-of-type span {
        text-align: right;
        left: -88px;
      }


       .form-range::-webkit-slider-runnable-track {
        background: #cbcbcb;
        height: 2px;
      }

       .form-range::-webkit-slider-thumb {
        width: 1.5rem;
        height: 1.5rem;
        cursor: pointer;
        -webkit-appearance: none;
        appearance: none;
        border-radius: 50%;
        border: 2px solid purple;
        box-shadow: inset 0px 0px 0px 2px white;
        background-color: purple;
        margin-top: -0.75rem;
      }

    </style>


    <script>
      function createComborangeContainer(comborangeData) {
        const container = document.createElement('div');
        container.classList.add('row');
        container.classList.add('combo-range');

        container.innerHTML = `
          <div class="col-sm-9">
            <div class="comborange-inner-container">
              <input type="range" min="1" max="1" value="1" class="form-range">
              <div class="comborange-dots"></div>
            </div>
          </div>
          <div class="col-sm-3">
            <select class="form-select comborange-dropdown"></select>
          </div>
      `;

        return container;
      }

      function initializeComborange(comborangeContainer, keyValuePairs, startValue) {
        const keys = Object.keys(keyValuePairs); 
        const values = Object.values(keyValuePairs); 

        // Build the select list; this will be the value that gets submitted in the form
        const dropdown = comborangeContainer.querySelector('.comborange-dropdown');
        keys.forEach((key, index) => {
          const option = document.createElement('option');
          option.value = values[index];
          option.textContent = key;
          dropdown.appendChild(option);
        });

        // Build the range for visualization of options
        const comborange = comborangeContainer.querySelector('input[type=range]');
        comborange.max = keys.length;

        // Set the initial value for the comborange and select dropdown
        const startIndex = values.indexOf(startValue);
        if (startIndex !== -1) {
          comborange.value = startIndex + 1;
          dropdown.value = values[startIndex];
        } else {
          comborange.value = 1; // Default to the first value if startValue is not found
          dropdown.value = values[0];
        }

        // Create the dots and labels below each step on the range
        const comborangeDots = comborangeContainer.querySelector('.comborange-dots');
        keys.forEach((key, index) => {
          const dot = document.createElement('div');
          comborangeDots.appendChild(dot);

          const valueLabel = document.createElement('span');
          valueLabel.textContent = key;
          dot.appendChild(valueLabel);
        });

        // Sync comborange with select dropdown
        comborange.oninput = function() {
          dropdown.value = values[this.value - 1];
        };

        // Sync select dropdown with comborange
        dropdown.onchange = function() {
          comborange.value = values.indexOf(parseInt(this.value)) + 1;
        };
      }

      function createComboranges() {
        const comboranges = document.querySelectorAll('.comborange-init');

        comboranges.forEach(comborange => {
          const keyValuePairs = JSON.parse(comborange.getAttribute('data-values'));
          const startValue = parseInt(comborange.getAttribute('data-start-value'), 10);
          const comborangeContainer = createComborangeContainer();
          comborange.appendChild(comborangeContainer);
          initializeComborange(comborangeContainer, keyValuePairs, startValue);
        });
      }

      createComboranges();

    </script>

</body>

</html>

© www.soinside.com 2019 - 2024. All rights reserved.