Ответ Toon Krijthe работает в большинстве случаев. Но иногда это приводит к избыточному количеству клещей. Он также не будет работать с отрицательными числами. Общий подход к проблеме приемлем, но есть способ лучше справиться с этим. Алгоритм, который вы хотите использовать, будет зависеть от того, что вы действительно хотите получить. Ниже я представляю вам свой код, который я использовал в своей библиотеке 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% уверенным, что мой график будет охватывать все данные. Также очень важно указать логарифм 10 диапазона, отрицательный он или нет, и вычесть 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 с таким же размером деления. Но это мой уволенный я оставляю это вам.
Надеюсь, поможет. Ура!