Is there any way to get the pixel position of the slider handle of an HTML5 range input ?
I ran into this same problem, where the label position was skewed at the far ends of the slider:
I noticed that the problem incrementally improved as you move towards the center of the slider and then incrementally got worse as you moved toward the other end:
I think what is happening is that because the thumb must not extend beyond the bounds of the slider track, half of the thumb's width is incrementally shaved from the thumb's position as it moves down the slider. The end result is that when the thumb's edge (not its center) reaches the end of the slider, the slider value is at its min or max.
So, to fix the skewed label, we need to calculate that dynamic offset. Here is an extra verbose offset calculation in an attempt to better explain the problem (and solution):
var half_thumb_width = 25/2;
var half_label_width = $(range_input).prev('span.rs-label').outerWidth()/2;
var slider_width = $(range_input).width();
var center_position = slider_length/2;
var percent_of_range = (range_input.value / (range_input.max - range_input.min));
var value_px_position = percent_of_range * slider_length;
var dist_from_center = value_px_position - center_position;
var percent_dist_from_center = dist_from_center / center_position;
var offset = percent_dist_from_center * half_thumb_width;
var final_label_position = value_px_position - half_label_width - offset;
I put together a quick demo of the problem and solution here: codepen demo
It was fun to figure out, but I hope this can help prevent others from spending the time.
Try this
val = slider.val();
// Measure width of slider element. adjust by 15 to account for padding/border
width = slider.width() - 15;
// Calculate percentage between left and right of input
min = slider.attr('min');
max = slider.attr('max');
percent = (val - min) / (max - min);
// Janky value to get pointer to line up better
offset = -3;
// the position of the output
newPosition = width * percent + offset;
slider.next('output')
.css({left: newPosition})
.text(val);
Adapted from here
Here is an alternative solution, basically get the mouse position and use that instead of the slider position. (some tweaking required, possibly)
Fiddle here: https://jsfiddle.net/brightertools/qdhp2g17/5/
CSS:
.sliderHolder{
margin: 0;
padding: 0;
position: relative;
border: 1px solid silver;
#slider{
width: 100%;
}
.tt{
position: absolute;
border: 1px solid grey;
top: 20px;
margin: 5px;
}
}
HTML:
<div class="sliderHolder">
<input type="range" min="0" max="100" id="slider" />
</div>
JS:
var dragging = false;
jQuery('#slider').on('input',function(){
dragging = true;
});
jQuery('#slider').on('mouseup',function(){
dragging = false;
});
jQuery('#slider').on('mousemove',function(e){
if (dragging == false)
{
return;
}
jQuery('.tt').remove();
var mouseX = e.clientX - 14;
jQuery('.tt').remove();
var slider = jQuery('#slider');
var sliderValue = jQuery('#slider').val();
jQuery('.sliderHolder').append('<div class="tt">' + sliderValue + '</div>');
jQuery('.tt').css({'left':mouseX + 'px'});
})
This worked for me:
var slider = $("#combicalc_contribution-slider")[0];
var sliderPos = slider.value / slider.max;
var pixelPostion = slider.clientWidth * sliderPos;
//this is your pixel value
console.log(pixelPostion);
The pixel value was calculated properly for values from 1 to 50, on your example.