Search code examples
javascriptsliderlogarithm

Logarithmic slider


I have a slider with values ranging from 0 to 100.

I want to map them to a range from 100 to 10,000,000.

I've seen some functions scattered around the net but they're all in C++. I need it in Javascript.

Any ideas?


Solution

  • 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.00000000000004
    js> logslider(10);
    316.22776601683825
    js> logslider(20);
    1000.0000000000007
    js> logslider(40);
    10000.00000000001
    js> logslider(60);
    100000.0000000002
    js> 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" />