Logarithmischer Schieberegler

Lesezeit: 9 Minuten

Benutzer-Avatar
Benutzer103773

Ich habe einen Schieberegler mit Werten von 0 bis 100.

Ich möchte sie einem Bereich von 100 bis 10.000.000 zuordnen.

Ich habe einige Funktionen im Netz verstreut gesehen, aber sie sind alle in C++. Ich brauche es in Javascript.

Irgendwelche Ideen?

Benutzer-Avatar
etw

Sie können eine Funktion wie diese verwenden:

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

Die resultierenden Werte entsprechen einer logarithmischen Skala:

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

Die umgekehrte Funktion würde mit den gleichen Definitionen für minp, maxp, minv, maxv und scaleberechnen Sie eine Schiebereglerposition aus einem Wert wie diesem:

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

Alles zusammen, verpackt in eine Klasse und als funktionales Code-Snippet, würde es so aussehen:

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

  • Besteht die Möglichkeit, dass Sie die entgegengesetzte Funktion haben? Geben Sie anhand des Protokollwerts aus, an welcher Position sich der Schieberegler befindet.

    – GeekyMonkey

    9. März 2011 um 16:21 Uhr

  • Ist das nicht ein Exponentialschieber? Gibt es eine Möglichkeit, die Kurve so umzukehren, dass sie logarithmisch ist? Damit der Wert schnell steigt und zum Ende hin langsamer wird?

    – Nick Hooked

    2. März 2017 um 10:53 Uhr

  • @NickH: Hängt davon ab, wie man es betrachtet. Wenn die Schiebereglerposition derzeit nach oben geht, steigt der zugehörige Wert immer schneller an, also aus dieser Perspektive ist es exponentiell. Wenn Sie es umgekehrt brauchen, wechseln Sie value und position um den gegenteiligen Effekt zu erzielen.

    – etw

    2. März 2017 um 23:17 Uhr

  • @sth Danke, ich werde immer mit Exponential und Logarithmus verwechselt. Gibt es eine Möglichkeit, die Kurve in Ihrer Lösung weniger schnell ansteigen zu lassen (linearer, aber immer noch exponentiell)? Bei einer Eingabe von 50 liegt der Wert irgendwo um 550.

    – Nick Hooked

    3. März 2017 um 9:28 Uhr

Um die gewünschte Verteilung zu erhalten, können Sie meiner Meinung nach diese Formel verwenden:

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

Hier ist eine eigenständige Seite, die die Werte druckt, die Sie für Ihren 0-100-Schieberegler erhalten, nachdem Sie sie durch diese Formel geleitet haben:

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

Die Zahlen reichen von 100 bis 10.000.000, was für mein mathematisch rostiges Auge die gewünschte Verteilung zu sein scheint. 😎

  • Begonnen mit Math.exp(i) und von Hand angepasst, bis die Zahlen passen. Mein Mathe-Fu ist schwach, aber ich kann für England binär hacken. 😎

    – Richie Hindle

    10. Mai 2009 um 22:47 Uhr

Beantwortet die Frage nicht ganz, aber für Interessierte ist die umgekehrte Zuordnung der letzten Zeile

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

nur um zu dokumentieren.

HINWEIS: Der Wert muss > 0 sein.

Benutzer-Avatar
NSjonas

Das Problem mit einem echten logarithmischen Schieberegler liegt am unteren Ende, mehrere Punkte auf dem Schieberegler führen wahrscheinlich zu doppelten Werten.

Aus reiner UI-Perspektive bietet es auch keine sehr intuitive Ausgabe für die Benutzereingabe.

Ich denke, eine bessere Option ist die Verwendung einer “gestuften” Transformation mit gleichmäßiger Verteilung.

Geben Sie hier die Bildbeschreibung ein

Mit anderen Worten, wir geben eine Reihe von Inkrementen an, die wir verwenden möchten (z. B.: 1, 10, 100, 1000). Dann teilen wir den Schieberegler in gleiche Teile auf, basierend auf der Anzahl der von uns definierten Inkremente. Wenn wir durch unsere verschiedenen Abschnitte gleiten, erhöht sich die Schiebereglerausgabe um die jeweilige Schrittweite.

FUNKTIONIERENDE DEMO

REAKTIONSCODE

Im obigen Beispiel definieren wir unsere min, max & intervals Reihe.

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

Wir müssen dann die Anzahl der diskreten Werte finden, die unser Schieberegler haben muss, damit er basierend auf unseren definierten Intervallverteilungen richtig vom Minimum zum Maximum geht.

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

In diesem Fall 535.

Notiz: Ihre Slider-Punkte sollten die Anzahl der Pixel im Slider nicht überschreiten

Schließlich transformieren wir einfach unsere Ausgabe mit dem oben beschriebenen Algorithmus. Das Codebeispiel leistet auch einige Arbeit, sodass die Ausgabe für das aktuelle Schrittintervall immer rund ist.

Ich suchte Logarithmischer Schieberegler für Angular aber ich kann keine finden und dann bin ich auf diese Antwort gestoßen,

Und das habe ich für Angular 2+ erstellt (Demo ist in Angular 6): FUNKTIONIERENDE DEMO

Dank an @etwfür Ausschnitt :

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

POW()-Funktion

Hier ist eine etwas andere Einstellung mit einer pow()-Funktion. Dies ermöglicht das Einstellen einer “schrägen” Kurve, die die Verteilung der Eingangs- <-> Ausgangskurve bestimmt. Eine andere umgestaltete Version ermöglicht das Einstellen des Schiebereglers von der logarithmischen (exponentiellen) Eingabe.

$(document).ready(function() {
  $('#test').change(function() {
    this.value = parseFloat(this.value).toFixed(2);
    widthSliderCurve = this.value;
  });
});

var widthSliderCurve = 0.42; // between -1 and 1 - governs the way the range is skewed

widthSlider.oninput = function() {
  var thisSlider = document.getElementById("widthSlider");


  var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
  var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
  var originalMax = 200.0; // these are set in the slider defintion in HTML
  var mappedOutputMin = 0.05; // this is the desired output min
  var mappedOutputMax = 10; // this is the desired output max
  var originalRange = originalMax - originalMin;
  var newRange = mappedOutputMax - mappedOutputMin;

  var zeroRefCurVal = thisSlider.value - originalMin; // zero referenced
  var normalizedCurVal = zeroRefCurVal / originalRange; // normalized to 0-1 output
  var rangedValue = ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);

  var outbox = document.getElementById("wSliderOutput");
  outbox.innerHTML = rangedValue;
  //paper.tool.LineWidth = rangedValue;
};



let setLogSlider = function(value, widthSliderCurve, sliderType, outputName) {
  /*** make sure constants match the oninput function values ***/
  var curve = Math.pow(10, widthSliderCurve);
  var originalMin = 1.0; // these are set in the slider defintion in HTML make sure they match!
  var originalMax = 200.0; // these are set in the slider defintion in HTML
  var mappedOutputMin = 0.05; // this is the desired output min
  var mappedOutputMax = 10; // this is the desired output max
  var originalRange = originalMax - originalMin;
  var newRange = mappedOutputMax - mappedOutputMin;
  var logToLinear = Math.pow((value - mappedOutputMin) / newRange, 1 / curve) * originalRange + originalMin;
  console.log("logToLinear ", logToLinear);
  // set the output box
  var outbox = document.getElementById("wSliderOutput");
  outbox.innerHTML = Number(value).toFixed(2);
  // set the linear scale on the slider
  document.querySelectorAll(".optionSliders").forEach((optSlider) => {
    if (optSlider.getAttribute("data-slider-type") == sliderType) {
      optSlider.value = logToLinear;
    }
    var outBox = document.getElementById(outputName);
    outBox.value = value;
  });
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<html>

<head>
  <title>Pow function for variable skew of data mapping</title>
</head>

<body>
  Enter a float between -1.0 and 1.0, hit return, and cycle the slider.</br>

  <input id="test" type="text" value="0.5" />

  <input id="widthSlider" sliderName="widthSlider" type="range" min="1" value="20" max="200" data-slider-type="linesWidth">
  <label for="widthSlider">L Width <span id="Width">
        <output id="wSliderOutput"></output>
        </span></label>
</body>

</html>

var widthSliderCurve = 0,42; // zwischen -1 und 1 – bestimmt die Art und Weise, wie der Bereich verzerrt wird

widthSlider.oninput = function () { var thisSlider = document.getElementById(“widthSlider”);

  var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
  var originalMin = 1.0;     // these are set in the slider defintion in HTML make sure they match!
  var originalMax = 200.0;   // these are set in the slider defintion in HTML
  var mappedOutputMin = 0.05; // this is the desired output min
  var mappedOutputMax = 10;  // this is the desired output max
  var originalRange = originalMax - originalMin;
  var newRange = mappedOutputMax - mappedOutputMin;

  var zeroRefCurVal = thisSlider.value - originalMin;      // zero referenced
  var normalizedCurVal  =  zeroRefCurVal / originalRange;  // normalized to 0-1 output
  var rangedValue =  ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);

  var outbox = document.getElementById("wSliderOutput");
  outbox.innerHTML = rangedValue;
  paper.tool.LineWidth = rangedValue;

 
  

  //setLogSlider(rangedValue, widthSliderCurve, "L_Width", "wSliderOutput2");

}; setLogSlider = function (value, widthSliderCurve, sliderType, outputName) { /*** sicherstellen, dass die Konstanten mit den oninput-Funktionswerten übereinstimmen ***/ var curve = Math.pow (10, widthSliderCurve); var originalMin = 1,0; // Diese sind in der Slider-Definition in HTML festgelegt, stellen Sie sicher, dass sie übereinstimmen! var originalMax = 200,0; // diese werden in der Slider-Definition in HTML gesetzt var mappedOutputMin = 0.05; // das ist die gewünschte Ausgabe min var mappedOutputMax = 10; // das ist die gewünschte Ausgabe max var originalRange = originalMax – originalMin; var newRange = mappedOutputMax – mappedOutputMin; var logToLinear = Math.pow ((value – mappedOutputMin) / newRange, 1 / curve) * originalRange + originalMin; console.log(“logToLinear”, logToLinear); // setze das Ausgabefeld var outbox = document.getElementById(“wSliderOutput”); outbox.innerHTML = Zahl(Wert).toFixed(2); // setze die lineare Skala auf dem Slider document.querySelectorAll(“.optionSliders”).forEach((optSlider) => { if (optSlider.getAttribute(“data-slider-type”) == sliderType) { optSlider.value = logToLinear; } var outBox = document.getElementById(outputName); outBox.value = value; }); };

var widthSliderCurve = 0,42; // zwischen -1 und 1 – bestimmt die Art und Weise, wie der Bereich verzerrt wird

widthSlider.oninput = function () { var thisSlider = document.getElementById(“widthSlider”);

  var curve = Math.pow(10, widthSliderCurve); // convert linear scale into lograthimic exponent for other pow function
  var originalMin = 1.0;     // these are set in the slider defintion in HTML make sure they match!
  var originalMax = 200.0;   // these are set in the slider defintion in HTML
  var mappedOutputMin = 0.05; // this is the desired output min
  var mappedOutputMax = 10;  // this is the desired output max
  var originalRange = originalMax - originalMin;
  var newRange = mappedOutputMax - mappedOutputMin;

  var zeroRefCurVal = thisSlider.value - originalMin;      // zero referenced
  var normalizedCurVal  =  zeroRefCurVal / originalRange;  // normalized to 0-1 output
  var rangedValue =  ((Math.pow(normalizedCurVal, curve) * newRange) + mappedOutputMin).toFixed(2);

  var outbox = document.getElementById("wSliderOutput");
  outbox.innerHTML = rangedValue;
  paper.tool.LineWidth = rangedValue;

};

1179110cookie-checkLogarithmischer Schieberegler

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy