Логарифмічний повзунок


82

У мене є повзунок зі значеннями від 0 до 100.

Я хочу відобразити їх у діапазоні від 100 до 10 000 000.

Я бачив деякі функції, розкидані по мережі, але всі вони перебувають на C ++. Мені це потрібно в Javascript.

Будь-які ідеї?

Відповіді:


185

Ви можете використовувати таку функцію:

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, maxvі 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" />


5
Будь-який шанс у вас буде протилежна функція? Враховуючи значення журналу, виведіть, у якому положенні повинен знаходитися повзунок.
GeekyMonkey

1
Хіба це не експоненціальний повзунок? Чи є спосіб змінити криву, щоб вона була логарифмічною? Так що значення швидко зростає, а потім до кінця йде повільно?
Нік Хук,

2
@NickH: Залежить від того, як ти на це дивишся. В даний час, коли положення повзуна піднімається вгору, пов'язане значення зростає все швидше і швидше, тому з цієї точки зору воно експоненціальне. Якщо вам потрібно навпаки, переключіться valueі, positionщоб отримати зворотний ефект.
sth

@sth Дякую, мене завжди плутають з експоненціальним та логаритмічним. Чи є спосіб зробити так, щоб крива у вашому рішенні йшла вгору менш швидкою (більш лінійною, але все одно експоненціальною)? При вході 50 значення становить десь близько 550.
Нік Хук,

9

Для отримання бажаного розподілу, я думаю, ви можете скористатися цією формулою:

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


4
Почав з Math.exp (i) і відрегулював вручну, поки цифри не збігаються. Моя математика-фу слабка, але я можу бінарно відбивати Англію. 8-)
RichieHindle

Ці дві відповіді представляють силу знань з математики .. Це повинно висловити будь-якому програмісту про вимогу вивчення математики.
asyncwait

9

Не зовсім відповідаючи на запитання, але для зацікавлених людей зворотне відображення останнього рядка

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

просто для документування.

ПРИМІТКА - значення має бути> 0.


5

Проблема із справжнім логарифмічним повзунком у нижньому кінці, кілька точок на повзуні, ймовірно, призведуть до повторення значень.

З точки зору чисто інтерфейсу користувача, він також не забезпечує дуже інтуїтивно зрозумілий результат для вводу користувачами.

Я думаю, що кращим варіантом є використання "ступінчастого" перетворення з рівномірним розподілом.

введіть тут опис зображення

Іншими словами, ми вказуємо ряд приростів, які ми хочемо використовувати (наприклад: 1, 10, 100, 1000). Потім ми розділяємо повзунок на рівні частини залежно від кількості кроків, які ми визначили. Коли ми ковзаємо по різних розділах, вихід повзунка збільшується на відповідний приріст.

РОБОЧА ДЕМО

РЕАГУЙТЕ КОД

У наведеному вище прикладі, ми визначаємо наш min, max& 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
Це чудово, дякую, що поділилися кодом! Я навіть не знав про повзунок реакції, тому Ch
Чак Бержерон,

Дуже приголомшливо! Ваш коментар був правдивим, цей метод досяг моєї мети набагато краще, ніж логарифмічна функція
Алекс

1

Я шукав логарифмічний повзунок для Angular, але не можу знайти жодного, і тоді я натрапив на цю відповідь,

І я створив це для Angular 2+ (Демо в Angular 6): РОБОЧА ДЕМО

Дякуємо @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;
   }
};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.