Dispositivo di scorrimento logaritmico
-
21-08-2019 - |
Domanda
Ho uno slider con valori che vanno da 0 a 100.
Voglio mapparli su un intervallo compreso tra 100 e 10.000.000.
Ho visto alcune funzioni sparse in rete ma sono tutte in C++.Mi serve in Javascript.
Qualche idea?
Soluzione
È possibile utilizzare una funzione come questa:
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));
}
I valori ottenuti corrispondono a una scala logaritmica:
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
La funzione inversa avrebbe, con le stesse definizioni di minp
, maxp
, minv
, maxv
e scale
, calcolare una posizione cursore da un valore così:
function logposition(value) {
// set minv, ... like above
// ...
return (Math.log(value)-minv) / scale + minp;
}
Tutti insieme, avvolto in una classe e come frammento di codice funzionale, sarebbe simile a questa:
// 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" />
Altri suggerimenti
Per ottenere la distribuzione che si desidera, penso che si può usare questa formula:
var value = Math.floor(-900 + 1000*Math.exp(i/10.857255959));
Ecco una pagina self-contained che stamperà i valori che si ottengono per il vostro 0-100 cursore, avendoli passò attraverso la 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>
I numeri vanno da 100 a 10 milioni in quello che sembra al mio occhio matematicamente-ruggine ad essere la distribuzione che si desidera. 8 -)
Non risponde del tutto alla domanda, ma per le persone interessate, la mappatura inversa dell'ultima riga è
return (Math.log(value)-minv)/scale + min;
solo per documentare.
NOTA il valore deve essere > 0.
ero alla ricerca di dispositivo di scorrimento logaritmica per angolare , ma non riesco a trovare alcuna e poi mi sono imbattuto in questa risposta,
E ho creato che per angolare 2+ (Demo è in angolare 6): LAVORO DEMO
Grazie alla @sth , per il frammento:
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;
}
};
Il problema con un vero cursore logaritmico è che all'estremità inferiore più punti sul cursore spesso daranno come risultato valori duplicati.
Dal punto di vista puramente dell'interfaccia utente, inoltre, non fornisce un output molto intuitivo per l'input degli utenti.
Penso che un'opzione migliore sia quella di utilizzare una trasformazione "a gradini" con distribuzione uniforme.
In altre parole, specifichiamo una serie di incrementi che vogliamo utilizzare (es:1, 10, 100, 1000).Quindi dividiamo il cursore in parti uguali in base al numero di incrementi che abbiamo definito.Quando scorriamo attraverso le nostre diverse sezioni, l'output del cursore aumenterà del rispettivo incremento.
Nell'esempio sopra, definiamo our min
, max
& intervals
vettore.
<ExpoStepSlider
intervals={[1, 2, 5, 10, 100, 1000]}
min={1}
max={50000}
/>
Dobbiamo quindi trovare il numero di valori discreti che il nostro dispositivo di scorrimento deve avere in modo che vada correttamente dal minimo al massimo in base alle nostre distribuzioni di intervalli definite.
let sliderPoints = Math.ceil(
(max - min) /
intervals.reduce((total, interval) => total + interval / intervals.length, 0)
);
In questo caso 535
.
Nota:I punti del dispositivo di scorrimento non devono superare il numero di pixel nel dispositivo di scorrimento
Infine, trasformiamo semplicemente il nostro output utilizzando l'algoritmo descritto sopra.Anche l'esempio di codice esegue alcune operazioni, quindi l'output è sempre rotondo per l'intervallo del passaggio corrente.