Die Antwort von Toon Krijthe funktioniert die meiste Zeit. Aber manchmal wird es eine übermäßige Anzahl von Zecken produzieren. Es wird auch nicht mit negativen Zahlen funktionieren. Die allgemeine Herangehensweise an das Problem ist in Ordnung, aber es gibt einen besseren Weg, um damit umzugehen. Der Algorithmus, den Sie verwenden möchten, hängt davon ab, was Sie wirklich erhalten möchten. Im Folgenden präsentiere ich Ihnen meinen Code, den ich in meiner JS Ploting-Bibliothek verwendet habe. Ich habe es getestet und es funktioniert immer (hoffentlich;)). Hier sind die wichtigsten Schritte:
- Holen Sie sich globale Extreme xMin und xMax (geben Sie alle Diagramme ein, die Sie im Algorithmus drucken möchten).
- Berechnen Sie den Bereich zwischen xMin und xMax
- Berechnen Sie die Größenordnung Ihres Bereichs
- Berechnen Sie die Zeckengröße, indem Sie den Bereich durch die Anzahl der Zecken minus eins teilen
- Dieser ist optional. Wenn Sie immer null Ticks drucken möchten, verwenden Sie die Tickgröße, um die Anzahl der positiven und negativen Ticks zu berechnen. Die Gesamtzahl der Ticks ist ihre Summe + 1 (das Null-Tick).
- Dieser wird nicht benötigt, wenn Sie immer null Häkchen gedruckt haben. Berechnen Sie die untere und obere Grenze, aber denken Sie daran, das Diagramm zu zentrieren
Lasst uns beginnen. Zuerst die Grundberechnungen
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);
Ich runde Minimal- und Maximalwerte, um 100% sicher zu sein, dass mein Plot alle Daten abdeckt. Es ist auch sehr wichtig, den Boden log10 des Bereichs zu bestimmen, ob er negativ ist oder nicht, und 1 später abzuziehen. Andernfalls funktioniert Ihr Algorithmus nicht für Zahlen, die kleiner als eins sind.
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);
Ich benutze "gut aussehende Zecken", um Zecken wie 7, 13, 17 usw. zu vermeiden. Die Methode, die ich hier verwende, ist ziemlich einfach. Es ist auch schön, bei Bedarf ZeroTick zu haben. Die Handlung sieht auf diese Weise viel professioneller aus. Sie finden alle Methoden am Ende dieser Antwort.
Jetzt müssen Sie die oberen und unteren Grenzen berechnen. Dies ist mit null Tick sehr einfach, erfordert aber in anderen Fällen etwas mehr Aufwand. Warum? Weil wir die Handlung innerhalb der oberen und unteren Grenze schön zentrieren wollen. Schauen Sie sich meinen Code an. Einige der Variablen werden außerhalb dieses Bereichs definiert, andere sind Eigenschaften eines Objekts, in dem der gesamte dargestellte Code gespeichert ist.
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;
}
Und hier sind Methoden, die ich zuvor erwähnt habe, die Sie selbst schreiben können, aber Sie können auch meine verwenden
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;
}
}
Es gibt nur noch eine Sache, die hier nicht enthalten ist. Dies ist die "gut aussehende Grenze". Dies sind Untergrenzen, die Zahlen sind, die den Zahlen in "gut aussehenden Zecken" ähnlich sind. Zum Beispiel ist es besser, wenn die Untergrenze bei 5 mit der Zeckengröße 5 beginnt, als wenn ein Diagramm bei 6 mit der gleichen Zeckengröße beginnt. Aber das habe ich dir überlassen.
Ich hoffe es hilft. Prost!