95 votes

Curseur logarithmique

J'ai un curseur dont les valeurs vont de 0 à 100.

Je veux les mettre en correspondance avec un intervalle de 100 à 10 000 000.

J'ai vu quelques fonctions dispersées sur le net mais elles sont toutes en C++. J'en ai besoin en Javascript.

Des idées ?

212voto

sth Points 91594

Vous pouvez utiliser une fonction comme celle-ci :

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

Les valeurs résultantes correspondent à une échelle logarithmique :

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 fonction inverse serait, avec les mêmes définitions de minp , maxp , minv , maxv et scale calculer la position du curseur à partir d'une valeur comme celle-ci :

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

Le tout, enveloppé dans une classe et sous forme d'extrait de code fonctionnel, ressemblerait à ceci :

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

5 votes

Y a-t-il une chance que vous ayez la fonction inverse ? Étant donné la valeur logarithmique, indiquez la position du curseur.

1 votes

N'est-ce pas un curseur exponentiel ? Y a-t-il un moyen d'inverser la courbe pour qu'elle soit logarithmique ? De façon à ce que la valeur augmente rapidement puis diminue vers la fin ?

2 votes

@NickH : Cela dépend de la façon dont vous voyez les choses. Actuellement, lorsque la position du curseur augmente, la valeur associée augmente de plus en plus vite, donc de ce point de vue, c'est exponentiel. Si vous en avez besoin dans l'autre sens, changez value et position pour obtenir l'effet inverse.

11voto

siliconeagle Points 2292

Cela ne répond pas tout à fait à la question, mais pour les personnes intéressées, la carte inverse de la dernière ligne est la suivante

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

juste pour documenter.

NOTE : la valeur doit être > 0.

11voto

NSjonas Points 1457

Le problème avec un véritable curseur logarithmique est qu'à l'extrémité inférieure, des points multiples sur le curseur entraîneront probablement des valeurs doubles.

Du point de vue de l'interface utilisateur, il ne fournit pas non plus une sortie très intuitive pour l'entrée des utilisateurs.

Je pense qu'une meilleure option est d'utiliser une transformation "étagée" à distribution égale.

enter image description here

En d'autres termes, nous spécifions une série d'incréments que nous voulons utiliser (ex : 1, 10, 100, 1000). Ensuite, nous divisons le curseur en parties égales sur la base du nombre d'incréments que nous avons défini. Lorsque nous glissons à travers nos différentes sections, la sortie du curseur sera incrémentée par l'incrément respectif.

DÉMO DE TRAVAIL

CODE DE RÉACTION

Dans l'exemple ci-dessus, nous définissons notre min , max & intervals le tableau.

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

Nous devons ensuite trouver le nombre de valeurs discrètes que doit avoir notre curseur pour qu'il aille correctement de min à max sur la base de nos distributions d'intervalles définies.

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

Dans ce cas 535 .

Note : Les points de votre curseur ne doivent pas dépasser le nombre de pixels du curseur.

Enfin, nous transformons simplement notre sortie en utilisant l'algorithme décrit ci-dessus. L'exemple de code effectue également un travail pour que la sortie soit toujours ronde pour l'intervalle de pas actuel.

9voto

RichieHindle Points 98544

Pour obtenir la distribution que vous souhaitez, je pense que vous pouvez utiliser cette formule :

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

Voici une page autonome qui imprimera les valeurs que vous obtiendrez pour votre curseur 0-100, après les avoir passées dans cette formule :

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

Les nombres vont de 100 à 10 000 000 dans ce qui semble être la distribution souhaitée à mon œil de mathématicien rouillé. 8-)

4 votes

J'ai commencé avec Math.exp(i) et j'ai ajusté à la main jusqu'à ce que les chiffres correspondent. Mon talent en maths est faible, mais je peux faire du binaire pour l'Angleterre. 8-)

2voto

Vivek Doshi Points 18852

Je cherchais Curseur logarithmique pour Angular mais je n'en trouve pas et puis je suis tombé sur cette réponse ,

Et j'ai créé cela pour Angular 2+ (la démo est en Angular 6) : DÉMO DE TRAVAIL

Merci à @sth pour l'extrait :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X