Die Antwort von Toon Krijthe funktioniert die meiste Zeit. Aber manchmal erzeugt es eine zu hohe Anzahl von Ticks. Es funktioniert auch nicht mit negativen Zahlen. Die allgemeine Herangehensweise an das Problem ist in Ordnung, aber es gibt einen besseren Weg, das Problem zu lösen. Welchen Algorithmus Sie verwenden wollen, hängt davon ab, was Sie wirklich erreichen wollen. Im Folgenden stelle ich Ihnen meinen Code vor, den ich in meiner JS Ploting-Bibliothek verwendet habe. Ich habe ihn getestet und er funktioniert immer (hoffentlich ;) ). Hier sind die wichtigsten Schritte:
- Ermitteln der globalen Extremwerte xMin und xMax (alle zu druckenden Diagramme in den Algorithmus einbeziehen)
- Bereich zwischen xMin und xMax berechnen
- Berechnen Sie die Größenordnung Ihrer Reichweite
- Berechnung der Tickgröße durch Division des Bereichs durch die Anzahl der Ticks minus eins
- dies ist fakultativ. Wenn Sie möchten, dass immer ein Null-Tick gedruckt wird, verwenden Sie die Tick-Größe, um die Anzahl der positiven und negativen Ticks zu berechnen. Die Gesamtzahl der Ticks ist deren Summe + 1 (der Null-Tick)
- Dies ist nicht erforderlich, wenn Sie immer Null-Zeichen drucken lassen. Berechnen Sie die untere und obere Grenze, aber denken Sie daran, die Darstellung zu zentrieren
Fangen wir an. Zunächst die grundlegenden Berechnungen
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 die Minimal- und Maximalwerte, um 100 % sicher zu sein, dass mein Diagramm alle Daten abdeckt. Es ist auch sehr wichtig, den log10-Wert des Bereichs zu unterteilen, unabhängig davon, ob er negativ ist oder nicht, und später 1 zu subtrahieren. 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 verwende "schön aussehende Häkchen", um Häkchen wie 7, 13, 17 usw. zu vermeiden. Die Methode, die ich hier verwende, ist ziemlich einfach. Es ist auch schön, zeroTick haben, wenn nötig. Der Plot sieht auf diese Weise viel professioneller aus. Sie finden alle Methoden am Ende dieser Antwort.
Nun müssen Sie Ober- und Untergrenzen berechnen. Dies ist bei einem Nulltick sehr einfach, erfordert aber in anderen Fällen ein wenig mehr Aufwand. Warum? Weil wir das Diagramm innerhalb der oberen und unteren Grenze zentrieren wollen. Werfen Sie einen Blick auf meinen Code. Einige der Variablen sind außerhalb dieses Bereichs definiert und einige von ihnen sind Eigenschaften eines Objekts, in dem der gesamte vorgestellte Code enthalten 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 die Methoden, die ich bereits 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 aufgeführt ist. Das sind die "schön aussehenden Schranken". Dabei handelt es sich um untere Grenzen, die den Zahlen in den "schön aussehenden Ticks" ähnlich sind. Zum Beispiel ist es besser, wenn die untere Grenze bei 5 mit der Tickgröße 5 beginnt, als wenn die Grafik bei 6 mit der gleichen Tickgröße beginnt. Aber das überlasse ich Ihnen.
Ich hoffe, es hilft. Prost!