Відповідь Тун Крейте працює більшу частину часу. Але іноді це призводить до надмірної кількості кліщів. Це не спрацює і з від’ємними числами. Загальний підхід до проблеми є нормальним, але є кращий спосіб вирішити цю проблему. Алгоритм, який ви хочете використовувати, буде залежати від того, що ви насправді хочете отримати. Нижче я представляю вам мій код, який я використав у своїй бібліотеці JS Ploting. Я перевірив це, і воно завжди працює (сподіваюся;)). Ось основні кроки:
- отримати глобальні екстремуми xMin та xMax (включити всі графіки, які ви хочете надрукувати в алгоритмі)
- обчислити діапазон між xMin та xMax
- обчисліть порядок величини вашого діапазону
- обчисліть розмір кліща, діливши діапазон на кількість кліщів мінус одиниця
- цей необов’язковий. Якщо ви хочете, щоб завжди було надруковано нульове позначення, ви використовуєте розмір галочки для обчислення кількості позитивних і негативних галочок. Загальна кількість кліків буде їх сумою + 1 (нульовий клік)
- цей не потрібен, якщо у вас постійно надруковано нульове позначення. Обчисліть нижню та верхню межі, але пам’ятайте про те, щоб відцентрувати графік
Давайте розпочнемо. Спочатку основні розрахунки
var range = Math.abs(xMax - xMin); //both can be negative
var rangeOrder = Math.floor(Math.log10(range)) - 1;
var power10 = Math.pow(10, rangeOrder);
var maxRound = (xMax > 0) ? Math.ceil(xMax / power10) : Math.floor(xMax / power10);
var minRound = (xMin < 0) ? Math.floor(xMin / power10) : Math.ceil(xMin / power10);
Я округляю мінімальні та максимальні значення, щоб бути на 100% впевненим, що мій графік охопить усі дані. Також дуже важливо підставити log10 діапазону приводу або ні, він є від’ємним і пізніше відняти 1. В іншому випадку ваш алгоритм не працюватиме для чисел, менших за одиницю.
var fullRange = Math.abs(maxRound - minRound);
var tickSize = Math.ceil(fullRange / (this.XTickCount - 1));
//You can set nice looking ticks if you want
//You can find exemplary method below
tickSize = this.NiceLookingTick(tickSize);
//Here you can write a method to determine if you need zero tick
//You can find exemplary method below
var isZeroNeeded = this.HasZeroTick(maxRound, minRound, tickSize);
Я використовую "приємні на вигляд кліщі", щоб уникати таких кліщів, як 7, 13, 17 тощо. Метод, який я використовую тут, досить простий. Також приємно мати zeroTick, коли це потрібно. Сюжет виглядає набагато професійніше. Усі методи ви знайдете в кінці цієї відповіді.
Тепер вам потрібно обчислити верхню і нижню межі. Це дуже просто з нульовою галочкою, але в іншому випадку потрібно трохи більше зусиль. Чому? Тому що ми хочемо красиво відцентрувати ділянку в межах верхньої та нижньої меж. Погляньте на мій код. Деякі змінні визначені поза цим обсягом, а деякі з них є властивостями об'єкта, в якому зберігається весь представлений код.
if (isZeroNeeded) {
var positiveTicksCount = 0;
var negativeTickCount = 0;
if (maxRound != 0) {
positiveTicksCount = Math.ceil(maxRound / tickSize);
XUpperBound = tickSize * positiveTicksCount * power10;
}
if (minRound != 0) {
negativeTickCount = Math.floor(minRound / tickSize);
XLowerBound = tickSize * negativeTickCount * power10;
}
XTickRange = tickSize * power10;
this.XTickCount = positiveTicksCount - negativeTickCount + 1;
}
else {
var delta = (tickSize * (this.XTickCount - 1) - fullRange) / 2.0;
if (delta % 1 == 0) {
XUpperBound = maxRound + delta;
XLowerBound = minRound - delta;
}
else {
XUpperBound = maxRound + Math.ceil(delta);
XLowerBound = minRound - Math.floor(delta);
}
XTickRange = tickSize * power10;
XUpperBound = XUpperBound * power10;
XLowerBound = XLowerBound * power10;
}
І ось методи, про які я згадав раніше, ви можете писати самостійно, але ви також можете використовувати мої
this.NiceLookingTick = function (tickSize) {
var NiceArray = [1, 2, 2.5, 3, 4, 5, 10];
var tickOrder = Math.floor(Math.log10(tickSize));
var power10 = Math.pow(10, tickOrder);
tickSize = tickSize / power10;
var niceTick;
var minDistance = 10;
var index = 0;
for (var i = 0; i < NiceArray.length; i++) {
var dist = Math.abs(NiceArray[i] - tickSize);
if (dist < minDistance) {
minDistance = dist;
index = i;
}
}
return NiceArray[index] * power10;
}
this.HasZeroTick = function (maxRound, minRound, tickSize) {
if (maxRound * minRound < 0)
{
return true;
}
else if (Math.abs(maxRound) < tickSize || Math.round(minRound) < tickSize) {
return true;
}
else {
return false;
}
}
Є ще одна річ, яка сюди не включена. Це "приємні на вигляд межі". Це нижчі межі, які є цифрами, подібними до цифр у "гарних на вигляд кліщах". Наприклад, краще мати нижню межу, починаючи з 5 з розміром галочки 5, ніж мати графік, який починається з 6 з однаковим розміром галочки. Але цю мою звільнену я залишаю вам.
Сподіваюся, це допоможе. На здоров’я!