Сделайте пользовательский слайдер диапазона, используя jQuery - PullRequest
1 голос
/ 08 ноября 2019

Я создал собственный слайдер. Я хочу изменить положение маркера, когда перетаскиваю ручку ползунка. Однако зазор между маркером и ручкой становится все больше по мере увеличения значения.

Я думаю, что проблема заключается в использовании позиционирования margin-left / left или absolute / relative.

Может кто-нибудь помочь мне выяснить, неверна ли концепция моего положения?

$(function() {
  $('.h-rs-line').on('input', function() {
    var val = $(this).val();
    var min = $(this).attr('min');
    var max = $(this).attr('max');
    var portion = (val - min) / (max - min);
    $('.h-rs-indicator').text(val);
    $('.h-rs-indicator').css('left', portion * $('.h-rs-line').width());
  });
});
body {
  background: #000;
}

.h-rs {
  position: relative;
}

.h-rs-index {
  color: #FFF;
}

.h-rs-container {
  display: flex;
  flex-direction: column;
  margin: 32px;
}

.h-rs-indicator {
  display: block;
  width: 50px;
  height: 35px;
  border-radius: 12px;
  text-align: center;
  line-height: 35px;
  background: #FFF;
  position: absolute;
  top: -30px;
  left: 0;
  margin-left: -16px;
}

.h-rs-indicator::after {
  content: '';
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 9px solid #FFF;
  position: absolute;
  top: 98%;
  left: 50%;
  margin-left: -8px;
}

.h-rs-line {
  width: 300px;
  margin-top: 24px;
  -webkit-appearance: none;
  border-radius: 24px;
}

.h-rs-line::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  height: 7px;
  border-radius: 24px;
}

.h-rs-line::-webkit-slider-thumb {
  -webkit-appearance: none;
  background: #FFF;
  height: 18px;
  width: 18px;
  border-radius: 100%;
  box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.25);
  margin-top: -5.5px;
}

.h-rs-index {
  display: flex;
  margin-top: 9px;
  width: 300px;
  justify-content: space-between;
}

.h-rs-index span:first-child {
  margin-left: 6.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="h-rs-container">
  <div class="h-rs">
    <span class="h-rs-indicator">0<span></span></span>
    <input class="h-rs-line" type="range" value="0" min="0" max="100" />
  </div>
  <div class="h-rs-index">
    <span>0</span><span>100</span>
  </div>
</div>

1 Ответ

1 голос
/ 08 ноября 2019

Компенсация ширины большого пальца

Вы забыли компенсировать размер большого пальца бегунка диапазона. Большой палец слайдера может перемещаться только на ширину слайдера минус размер большого пальца (таким образом, 300px минус ~ 18px). Поскольку большой палец может перемещаться только на 282 пикселя, метка должна быть, иначе они будут не синхронизированы.

Поэтому это:

$('.h-rs-indicator').css('left', portion * $('.h-rs-line').width());

... должно стать таким:

$('.h-rs-indicator').css('left', portion * ($('.h-rs-line').width() - 18));

... где 18 - ширина ползунка диапазона в пикселях.

$(function() {
  $('.h-rs-line').on('input', function() {
    var val = $(this).val();
    var min = $(this).attr('min');
    var max = $(this).attr('max');
    var portion = (val - min) / (max - min);
    $('.h-rs-indicator').text(val);
    $('.h-rs-indicator').css('left', portion * ($('.h-rs-line').width() - 18));
  });
});
body {
  background: #000;
}

.h-rs {
  position: relative;
}

.h-rs-index {
  color: #FFF;
}

.h-rs-container {
  display: flex;
  flex-direction: column;
  margin: 32px;
}

.h-rs-indicator {
  display: block;
  width: 50px;
  height: 35px;
  border-radius: 12px;
  text-align: center;
  line-height: 35px;
  background: #FFF;
  position: absolute;
  top: -30px;
  left: 0;
  margin-left: -16px;
}

.h-rs-indicator::after {
  content: '';
  width: 0;
  height: 0;
  border-left: 8px solid transparent;
  border-right: 8px solid transparent;
  border-top: 9px solid #FFF;
  position: absolute;
  top: 98%;
  left: 50%;
  margin-left: -8px;
}

.h-rs-line {
  width: 300px;
  margin-top: 24px;
  -webkit-appearance: none;
  border-radius: 24px;
}

.h-rs-line::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  height: 7px;
  border-radius: 24px;
}

.h-rs-line::-webkit-slider-thumb {
  -webkit-appearance: none;
  background: #FFF;
  height: 18px;
  width: 18px;
  border-radius: 100%;
  box-shadow: 0px 10px 10px rgba(0, 0, 0, 0.25);
  margin-top: -5.5px;
}

.h-rs-index {
  display: flex;
  margin-top: 9px;
  width: 300px;
  justify-content: space-between;
}

.h-rs-index span:first-child {
  margin-left: 6.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="h-rs-container">
  <div class="h-rs">
    <span class="h-rs-indicator">0<span></span></span>
    <input class="h-rs-line" type="range" value="0" min="0" max="100" />
  </div>
  <div class="h-rs-index">
    <span>0</span><span>100</span>
  </div>
</div>

Кроссбраузер

Получение ползунка диапазона, чтобы он выглядел одинаково (и был одинакового размера) в каждомБраузер включает в себя много CSS. Это очень хорошо объясняется в этой статье о хитростях CSS: https://css -tricks.com / styling-cross-browser-compatibility-range-input-css /


Non-jQuery

Как насчет переписать с jQuery на не-jQuery? Это может быть намного легче ... Примерно так:

<input type="range" min="0" max="100" oninput="updateRangeSlider(this)" onchange="updateRangeSlider(this)" />

С помощью этой функции в нижнем колонтитуле:

function updateRangeSlider(el){
    var val = el.value;
    var min = el.getAttribute('min');
    var max = el.getAttribute('max');
    var portion = (val - min) / (max - min);
    var iel = el.parentNode.querySelector('.h-rs-indicator');
    iel.innerHTML = val + '<span></span>';
    iel.style.left = (portion * (el.offsetWidth-18)) + 'px';
} 

Обратите внимание, что эта функция может использоваться повторно.

...