Mariusz Dabrowski님의 codepen 의 소스를 일부 수정 정리 중인 코드 입니다.
link : https://codepen.io/MarioD/pen/WwXbgr
range의 다양한 커트롤을 하기 위해 검색을 하다 알게 되었습니다.
다양하게 수정하여 사용 할 수 있을 것 같습니다.
그 외 순수 html input range type 을 이용한 소스도 있다.
Leena Lavanya의 소스링크를 적어 놓는다
link : https://codepen.io/leenalavanya/pen/yOWgog
/***** html *****/
<div class="zi-ranges">
<div id="slider-range"></div>
<div class="range-wrapper">
<div class="range"></div>
<div class="range-alert">+</div>
<div class="gear-wrapper">
<div class="gear-large gear-one">
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
</div>
<div class="gear-large gear-two">
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
<div class="gear-tooth"></div>
</div>
</div>
</div>
<div class="marker-box">
<div class="marker marker-0">최저가</div>
<div class="marker marker-25"><sup>$</sup>35,000</div>
<div class="marker marker-50"><sup>$</sup>60,000</div>
<div class="marker marker-75"><sup>$</sup>85,000</div>
<div class="marker marker-100">최고가</div>
</div>
</div>
/**** css *****/
/* Slider */
.zi-ranges {position:relative; padding:50px 20px;}
.ui-slider {background:#efefef; border:1px solid #d2d2d2; height:10px; position:relative; border-radius:100px;}
.ui-slider-range {background:#71c0ff; height:100%; position:absolute; border-top:1px solid #5d99c8; border-bottom:1px solid #5d99c8; transform:translateY(-1px);}
.ui-slider-range::after {content:""; width:100%; height:1px; background:#fff; position:absolute; top:0; left:0; opacity:0.3;}
.ui-slider-handle {background:#555; position:absolute; width:32px; height:32px; top:50%; display:block; transform:translate(-50%, -50%); border-radius:100px; z-index:10; background:linear-gradient(#555, #454545); cursor:move; cursor:grab; cursor:-moz-grab; cursor:-webkit-grab; box-shadow:inset -2px -2px 6px 2px rgba(0,0,0,0.1); transition:width 0.1s;}
.ui-slider-handle:focus {outline:none;}
.ui-slider-handle:active {cursor:grabbing;cursor:-moz-grabbing; cursor:-webkit-grabbing;}
.ui-state-active {width:22px;}
/* Range Indicator */
.range-wrapper {position:absolute; top:-50px; left:50%; transform:translateX(-50%);}
.range {background: #fff; white-space: nowrap; border: 1px solid #d2d2d2; border-radius: 2px; font-size: 13px; letter-spacing: 0.02em; color: #555; width: 150px; z-index: 10; position:relative;}
.range-wrapper:after {content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border-left: 67px solid transparent; border-right: 67px solid transparent; border-top: 6px solid #d2d2d2;}
.range-value {width: 74px; padding: 8px 0; text-align: center; display: inline-block; transition:background 0.1s;}
.range-divider {width: 1px; display: inline-block;}\
.range-divider:after {position: absolute; top: 0; left: 50%; width: 1px; height: 100%; background: #d2d2d2; content: '';}
.range-alert {width: 16px; height: 16px; position: absolute; top: 50%; right: 0; transform: translateY(-50%); background: #fff; border-top-right-radius: 2px; border-bottom-right-radius: 2px; border: 1px solid #d2d2d2; color: #0E0E0E; line-height: 15px; transition: right 0.2s;}
.range-alert.active {right: -15px;}
/* Price Markers */
.marker-box {position:absolute; bottom:0; width:100%;}
.marker {position:absolute; bottom:0; font-size:13px; color:#555; letter-spacing: 0.05em; transform:translateX(-50%);}
.marker::after{content:''; width:1px; height:8px; background:#d2d2d2; position:absolute; top:0; left:50%; transform:translateX(-50%);}
.marker-0::after {display:none;}
.marker-25 {left:25%;}
.marker-50 {left:50%;}
.marker-75 {left:75%;}
.marker-100 {right:0;}
.marker-100::after {display:none;}
/* Gears */
.gear-wrapper {position:absolute; top:-14px; left:50%; transform:translateX(-50%); z-index:5; backface-visibility:hidden; width:150px; height:20px; overflow:hidden;}
.gear-large {width:40px; height:40px; background:#d2d2d2; border-radius:100px; position:absolute; top:18px; left:18px; transform-origin:50% 50%; transition:top 0.15s;}
.gear-large::after {position:absolute; content:''; width:28px; height:28px; top:50%; left:50%; transform:translate(-50%, -50%); background:#e8e8e8; border-radius:100px;}
.gear-large:nth-child(2) {background:#d2d2d2; left:auto; right:18px;}
.gear-large:nth-child(2) .gear-tooth{background:#d2d2d2;}
.gear-large.active {top:4px;}
.gear-tooth{width:22%; height:114%; position:absolute; top:50%; left:50%; transform:translate(-50%, -50%); transform-origin:0 0; background:#d2d2d2; border-radius:2px;}
.gear-tooth:nth-child(2){transform:rotate(90deg) translate(-50%, -50%);}
.gear-tooth:nth-child(3){transform:rotate(45deg) translate(-50%, -50%);}
.gear-tooth:nth-child(4){transform:rotate(-45deg) translate(-50%, -50%);}
/***** js(jquery) *****/
$(function() {
// Initiate Slider1
$('#slider-range').slider({
range: true,
min: 100000,
max: 1000000,
step: 100,
values: [50000,1300000]
});
// Move the range wrapper into the generated divs
$('.ui-slider-range').append($('.range-wrapper'));
// Apply initial values to the range container
$('.range').html('<span class="range-value"><sup>$</sup>' + $('#slider-range').slider("values", 0).toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") + '</span><span class="range-divider"></span><span class="range-value"><sup>$</sup>' + $("#slider-range").slider("values", 1).toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") + '</span>');
// Show the gears on press of the handles
$('.ui-slider-handle, .ui-slider-range').on('mousedown', function() {
$('.gear-large').addClass('active');
});
// Hide the gears when the mouse is released
// Done on document just incase the user hovers off of the handle
$(document).on('mouseup', function() {
if ($('.gear-large').hasClass('active')) {
$('.gear-large').removeClass('active');
}
});
// Rotate the gears
var gearOneAngle = 0,
gearTwoAngle = 0,
rangeWidth = $('.ui-slider-range').css('width');
$('.gear-one').css('transform', 'rotate(' + gearOneAngle + 'deg)');
$('.gear-two').css('transform', 'rotate(' + gearTwoAngle + 'deg)');
$('#slider-range').slider({
slide: function(event, ui) {
// Update the range container values upon sliding
$('.range').html('<span class="range-value"><sup>$</sup>' + ui.values[0].toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") + '</span><span class="range-divider"></span><span class="range-value"><sup>$</sup>' + ui.values[1].toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,") + '</span>');
// Get old value
var previousVal = parseInt($(this).data('value'));
// Save new value
$(this).data({
'value': parseInt(ui.value)
});
// Figure out which handle is being used
if (ui.values[0] == ui.value) {
// Left handle
if (previousVal > parseInt(ui.value)) {
// value decreased
gearOneAngle -= 7;
$('.gear-one').css('transform', 'rotate(' + gearOneAngle + 'deg)');
} else {
// value increased
gearOneAngle += 7;
$('.gear-one').css('transform', 'rotate(' + gearOneAngle + 'deg)');
}
} else {
// Right handle
if (previousVal > parseInt(ui.value)) {
// value decreased
gearOneAngle -= 7;
$('.gear-two').css('transform', 'rotate(' + gearOneAngle + 'deg)');
} else {
// value increased
gearOneAngle += 7;
$('.gear-two').css('transform', 'rotate(' + gearOneAngle + 'deg)');
}
}
if (ui.values[1] === 110000) {
if (!$('.range-alert').hasClass('active')) {
$('.range-alert').addClass('active');
}
} else {
if ($('.range-alert').hasClass('active')) {
$('.range-alert').removeClass('active');
}
}
}
});
// Prevent the range container from moving the slider
$('.range, .range-alert').on('mousedown', function(event) {
event.stopPropagation();
});
});
$(document).ready(function () {
var isTouchDevice = 'ontouchstart' in document.documentElement;
$('.range, .range-alert').mousedown(function(event) {
if (isTouchDevice == false) {
pushed();
}
});
$('.range, .range-alert').mouseup(function(event) {
if (isTouchDevice == false) {
released();
}
});
$('.range, .range-alert').on('touchstart', function(){
if (isTouchDevice) {
pushed();
}
});
$('.range, .range-alert').on('touchend', function(){
if (isTouchDevice) {
released();
}
});
});