web-dev-qa-db-ja.com

対数スライダー

値が0〜100のスライダーがあります。

100から10,000,000の範囲にマップしたい。

私はいくつかの関数がネットに散らばっているのを見てきましたが、それらはすべてC++です。 Javascriptで必要です。

何か案は?

69
user103773

次のような関数を使用できます。

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

逆関数は、minpmaxpminvmaxv、およびscaleの同じ定義で、スライダー位置を計算しますこのような値:

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

必要な分布を取得するには、次の式を使用できます。

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>

数が100から10,000,000になり、数学的に錆びた目では、希望する分布になります。 8-)

9
RichieHindle

質問にはまったく答えていませんが、興味のある人にとっては、最後の行の逆マッピングは

return (Math.log(value)-minv)/scale + min;

文書化するだけです。

注:値は> 0でなければなりません。

9
siliconeagle

真の対数スライダーの問題は下端にあり、スライダー上の複数のポイントが重複した値になる可能性があります。

純粋にUIの観点から見ると、ユーザー入力に対して非常に直感的な出力も提供しません。

より良いオプションは、均等分布の「ステップ」変換を使用することだと思います。

enter image description here

つまり、使用する一連の増分を指定します(例:1、10、100、1000)。次に、定義した増分の数に基づいて、スライダーを等しい部分に分割します。異なるセクションをスライドすると、スライダーの出力はそれぞれの増分で増加します。

ワーキングデモ

REACT CODE

上記の例では、minmaxおよびintervals配列を定義します。

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

次に、定義された間隔分布に基づいてスライダーが最小値から最大値に適切に移動するように、スライダーに必要な離散値の数を見つける必要があります。

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

この場合 535

:スライダーポイントは、スライダー

最後に、上記のアルゴリズムを使用して出力を変換します。また、コード例ではいくつかの作業も行われるため、出力は常に現在のステップ間隔でラウンドされます。

2
NSjonas

私はを探していましたAngularの対数スライダー

そして、私はAngular= 2+(デモはAngular 6)にあります):WORKING DEMO

@ sthに感謝します。

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;
   }
};
1
Vivek Doshi