Logarithmic slider
You can use a function like this:
function logslider(position) { // position will be between 0 and 100 var minp = 0; var maxp = 100; // The result should be between 100 an 10000000 var minv = Math.log(100); var maxv = Math.log(10000000); // calculate adjustment factor var scale = (maxv-minv) / (maxp-minp); return Math.exp(minv + scale*(position-minp));}
The resulting values match a logarithmic scale:
js> logslider(0);100.00000000000004js> logslider(10);316.22776601683825js> logslider(20);1000.0000000000007js> logslider(40);10000.00000000001js> logslider(60);100000.0000000002js> logslider(100);10000000.000000006
The reverse function would, with the same definitions for minp
, maxp
, minv
, maxv
and scale
, calculate a slider position from a value like this:
function logposition(value) { // set minv, ... like above // ... return (Math.log(value)-minv) / scale + minp;}
All together, wrapped in a class and as a functional code snippet, it would look like this:
// Generic class: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: 20, minval: 100, maxval: 10000000});$('#slider').on('change', function() { var val = logsl.value(+$(this).val()); $('#value').val(val.toFixed(0));});$('#value').on('keyup', function() { var pos = logsl.position(+$(this).val()); $('#slider').val(pos);});$('#value').val("1000").trigger("keyup");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>Input value or use slider:<input id="value" /><input id="slider" type="range" min="0" max="20" />
To get the distribution you want, I think you can use this formula:
var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959));
Here's a self-contained page that will print the values you'll get for your 0-100 slider, having passed them through that formula:
<html><body><script>for (var i = 0; i <= 100; i++) { var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959)); document.write(value + "<br>");}</script></body></html>
The numbers go from 100 to 10,000,000 in what looks to my mathematically-rusty eye to be the distribution you want. 8-)
Not quite answering the question, but for people interested, the reverse maping the last line is
return (Math.log(value)-minv)/scale + min;
just to document.
NOTE the value must be > 0.