Summary
I need a range input with numbers from 1,000 to 10,000,000. Due to the large range it can't be linear. So each time the decimal length increases (eg from 1000 to 10000) the steps should also increase.
#--------------------#--------------------#--------------------#--------------------#
0 1000 5000 9000 10,000 56,498 100,000 500,000 1,000,000 10,000,000
Failed attempts
I already tried to create a slider range from 1 to 5 (to have 4 steps) and interpolate the values but I couldn't get it to work so the steps increased at the same time when the decimal increased.
Also I tried this solution: Logarithmic slider It's better than a linear behavior but still the steps in the beginning (left) are too small and too large in the end (right end of range slider).
Additional requirement
This range slider also has to be connected to an input field. So the input value also has to be written back to the slider (so some kind of inverse calculation input <-> range slider).
Adjusted version of the Logarithmic Slider solution linked above:
function LogSlider(options) { options = options || {}; this.minpos = options.minpos || 0; this.maxpos = options.maxpos || 100; this.minlval = Math.log(options.minval || 1); this.maxlval = Math.log(options.maxval || 100000); this.scale = (this.maxlval - this.minlval) / (this.maxpos - this.minpos); } LogSlider.prototype = { // Calculate value from a slider position value: function(position) { return Math.exp((position - this.minpos) * this.scale + this.minlval); }, // Calculate slider position from a value position: function(value) { return this.minpos + (Math.log(value) - this.minlval) / this.scale; } }; // Usage: var logsl = new LogSlider({maxpos: 300, minval: 1000, maxval: 10000000}); $('#slider').on('change input', function() { var val = logsl.value(+$(this).val()); // console.log(val); var rounded = Math.round(val / 1000) * 1000; var localized = rounded.toLocaleString('DE'); $('#value').val(localized); }); $('#value').on('keyup', function() { var val = +($(this).val().toString().replace(/[\D]/g,'')); //console.log(this.value, val); var pos = logsl.position(val); //console.log(pos); $('#slider').val(pos); }); $('#value').val("10000").trigger("keyup");
#slider { width: 300px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> Input value or use slider: <input id="value" /> <input id="slider" type="range" min="0" max="300" />
The smallest steps are 1,000. Here you can see, between 1,000 and 2,000 there are around 20 px space. But on very high numbers, the steps are up to over 300,000. So not the best user experience. You should at least be able to input in steps of 100,000 as illustrated above.
To get you started, you could get the right base for the slider.
function updateSlider() { let value = +document.getElementById('value').value, adjusted = Math.max(Math.min(value, max), min); document.getElementById('slider').value = Math.log(adjusted / min) / Math.log(base); updateValue(); } function updateValue() { const value = document.getElementById('slider').value; document.getElementById('value').value = (min * base ** value).toFixed(0); } const min = 1_000, max = 10_000_000, steps = +document.getElementById('slider').max, base = Math.pow(max / min, 1 / steps); document.getElementById('value').addEventListener('change', updateSlider); document.getElementById('slider').addEventListener('click', updateValue);
<input id="value" /> <input id="slider" type="range" min="0" max="20" />
Not a Javascript coder so I will not touch any of the stuff however you can use linear slide and use conversion between linear and logarithmic scales:
// linear x to logarithmic xx
if (x>=xmin) xx=log(x/xmin)/log(xmax/xmin)
else xx=0.0;
// logarithmic xx to linear x
x=exp(xx*log(xmax/xmin))*xmin;
Where xmin,xmax
is your range. Beware it can not include zero !!! so for example:
xmin=1.0;
xmax=10000000.0;
the xmin
can be anything bigger than 0
for example 0.001
and xmax
must be bigger than xmin
usually xmin*pow(10,?)
...
So x
is the slider linear position from xmin
to xmax
and xx
is logarithmic position in range <0.0,1.0>
So you just simply multiply the xx
by your resolution in pixels of your view/slider what ever to get [pixels]
...
I use conversions like this time to time here an example:
where xmin=100; xmax=22050;
xmin=100; xmax=22050;
from my spectroscope app.
Here 3D interpolation between curves another example with C++ code
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.