简体   繁体   English

使用 jQuery 制作自定义范围 slider

[英]Make a custom range slider using jQuery

I have created a custom slider.我创建了一个自定义 slider。 I want to make the position of the marker change as I drag the slider handle.当我拖动 slider 手柄时,我想让标记的 position 发生变化。 However the gap between the marker and the handle is getting wider as the value gets bigger.然而,随着值变大,标记和手柄之间的间隙越来越大。

I think the problem is to do with using margin-left / left or absolute / relative positioning.我认为问题与使用margin-left / leftabsolute / relative定位有关。

Can anyone help me to figure out if the concept of the position of mine is wrong?谁能帮我弄清楚我的 position 的概念是否错误?

 $(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>

Compensate for the thumb width补偿拇指宽度

You forgot to compenstate for the size of the range slider thumb.您忘记补偿 slider 拇指范围的大小。 The slider thumb can only travel the width of the slider minus the size of the thumb (so 300px minus ~18px). slider 拇指只能移动 slider 的宽度减去拇指的大小(所以 300px 减去 ~18px)。 Because the thumb can only travel 282px, so should the label, or they will be out of sync.因为拇指只能移动 282px,label 也应该这样,否则它们会不同步。

Therefore this:因此:

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

... should become this: ...应该变成这样:

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

... where 18 is the width of the range slider thumb in pixels. ... 其中 18 是 slider 拇指范围的宽度(以像素为单位)。

 $(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>


Cross-browser跨浏览器

Getting your range slider to look the same (and being the same size) in every browser involves a lot of CSS.让您的范围 slider 在每个浏览器中看起来都相同(并且大小相同)涉及很多 CSS。 This is explained very well in this article on CSS tricks: https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/这在这篇关于 CSS 技巧的文章中得到了很好的解释: https://css-tricks.com/styling-cross-browser-compatible-range-inputs-css/


Non-jQuery非 jQuery

How about a rewrite from jQuery to non-jQuery?从 jQuery 重写为非 jQuery 怎么样? That could be much lighter... Something like this:这可能会更轻......像这样的东西:

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

With this function in the footer:在页脚中使用此 function:

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';
} 

Note that this function is reusable.请注意,此 function 是可重复使用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM