developer tip

로그 슬라이더

copycodes 2020. 11. 3. 08:16
반응형

로그 슬라이더


0에서 100 사이의 값을 가진 슬라이더가 있습니다.

100에서 10,000,000 사이의 범위로 매핑하고 싶습니다.

인터넷에 흩어져있는 일부 함수를 보았지만 모두 C ++로되어 있습니다. Javascript로 필요합니다.

어떤 아이디어?


다음과 같은 기능을 사용할 수 있습니다.

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));
}

결과 값은 로그 스케일과 일치합니다.

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

반대 기능에 대한 정의와 동일한 것 minp, maxp, minv, maxvscale, 이런 값으로부터 슬라이더 위치를 계산 :

function logposition(value) {
   // set minv, ... like above
   // ...
   return (Math.log(value)-minv) / scale + minp;
}


모두 함께 클래스에 래핑되고 기능 코드 스 니펫은 다음과 같습니다.

// 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" />


원하는 분포를 얻으려면 다음 공식을 사용할 수 있습니다.

var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959));

다음은 해당 수식을 통해 값을 전달하여 0-100 슬라이더에 대해 얻을 수있는 값을 인쇄하는 자체 포함 된 페이지입니다.

<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.


The problem with a true Logarithmic slider is at the low end, multiple points on the slider will likely result in duplicate values.

From purely UI perspective, it also doesn't provide a very intuitive output for the users input.

I think a better option is to use an even-distribution "stepped" transform.

enter image description here

In other words, we specify a series of increments we want to use (ex: 1, 10, 100, 1000). Then we split the slider into equal parts based on the number of increments we defined. When we are sliding through our different sections, the slider output will increment by the respective increment.

WORKING DEMO

REACT CODE

In the above example, we define our min, max & intervals array.

<ExpoStepSlider
  intervals={[1, 2, 5, 10, 100, 1000]}
  min={1}
  max={50000}
/>

We then must find the number of discrete values our slider must have so that it properly goes from min to max based on our defined interval distributions.

let sliderPoints = Math.ceil(
  (max - min) / 
  intervals.reduce((total, interval) => total + interval / intervals.length, 0)
);

In this case 535.

Note: Your slider points should not exceed the number of pixels in the slider

Finally, we just transform our output using the algorithm described above. The code example also does some work so the output is always round for the the current step interval.


I was searching for Logarithmic slider For Angular but can't find any and then I came across this answer ,

And I have created that for Angular 2+ (Demo is in Angular 6) : WORKING DEMO

Thanks to @sth, for snippet :

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;
   }
};

참고URL : https://stackoverflow.com/questions/846221/logarithmic-slider

반응형