D3.js Zeitskala: Gut abgestufte Ticks in Minutenintervallen, wenn Daten in Sekunden sind?

8

Ich arbeite mit einer D3-Zeitskala. Meine Eingabedaten sind in Sekunden und es sind Dauerdaten statt Daten - also 10 Sekunden, 30 Sekunden usw.

Ich möchte eine Achse erstellen, die mir Folgendes ermöglicht:

  • Zeigt Ticks an, die in Minuten und Sekunden formatiert sind: wie "0m 30s", "1m 00s" usw. Diese Formatierung ist ziemlich einfach, aber nicht, wenn ich auch ...
  • brauche
  • Die Ticks werden in Intervallen angezeigt, die in Minutenschnelle ordentlich aussehen. Wenn ich nur die Standard-Tick-Formatierung von D3 verwende, bekomme ich Ticks in Intervallen, die in Minuten, aber nicht in Sekunden sinnvoll sind.

Hier ist mein Code:

%Vor%

Das gibt mir schön formatierte Ticks in unregelmäßigen Abständen: "16m 40s", "33m 20s" usw. Wie kann ich Ticks bei "10m 00s", "20m 00s", etc. erzeugen?

Die offensichtliche Antwort wäre, das Werte-Array in Minuten zu transformieren, eine lineare Skala zu verwenden und einen Formatierer zu schreiben, um damit umzugehen, aber ich würde, wenn möglich, lieber eine Zeitskala verwenden

Hier ist ein JSFiddle, um das Problem zu demonstrieren: Ссылка

    
Richard 02.07.2014, 21:26
quelle

1 Antwort

24

Wenn Sie eine Zeitskala erstellen, verwenden Sie normalerweise d3.time.scale() und nicht a lineare Skalierung.

Ihr Fall ist ein wenig seltsam, da Sie für Ihre Daten abstrakte Dauern der Zeit und keine spezifischen Punkte verwenden. Leider scheint die eingebaute Funktionalität von d3 für diesen Fall nicht gut geeignet zu sein. Es gibt ein paar Möglichkeiten, die ich mir für Workarounds vorstellen kann:

Option 1: Verwenden Sie eine lineare Skala mit manual .tickValues()

Anstatt die Ticks mit einem Date -Objekt zu formatieren. Sie könnten einfach Ihren Datenwert (in Sekunden) in Stunden, Minuten und Sekunden aufschlüsseln. Etwas wie das:

%Vor%

Im Grunde nimmt dies die Gesamtanzahl der Sekunden in Anspruch, erzeugt eine Stunde für alle 3600 Sekunden, erstellt für jede verbleibende 60 Sekunden eine Minute und gibt schließlich die verbleibenden Sekunden zurück. Dann gibt es eine String-Repräsentation aus, zum Beispiel: 17s oder 12m 42s oder 4h 8m 22s .

Wenn Sie dann Ihre Achse erstellen, können Sie mit der .tickValues() -Methode einen Bereich von Null bis zum maximalen Wert Ihrer Daten zuweisen, wobei Sie in Schritten von 600 vorgehen, da es in 10 Minuten 600 Sekunden gibt. Das würde so aussehen:

%Vor%

Hier ist ein JSFiddle der Ausgabe.

Option 2: Verwenden Sie eine Zeitskala mit einer festen Dauer für .ticks()

Mit den Zeitskalen können Sie alle 10 Minuten direkt angeben, dass Sie Ticks möchten. Sie tun dies, indem Sie einfach eine d3-Dauer und einen Multiplikator an die Methode .ticks() Ihrer Achse übergeben. So:

%Vor%

Um dies zu tun, müssen Sie zuerst Ihre Zeitskala einrichten. Für die Domäne Ihrer Skalierung können Sie einen Bereich von Millisekundenwerten verwenden, da d3 diese in Date -Objekte umwandelt. Da Ihre Daten in Sekunden sind, können wir einfach mit 1000 multiplizieren, um Millisekunden zu erhalten. In diesem Fall runden wir den Maximalwert auf die nächste Millisekunde auf, da es eine Ganzzahl sein muss, um ein gültiges Datum zu erhalten:

%Vor%

Schließlich können Sie Ihr Format mit .tickFormat() :

direkt an die Achse übergeben %Vor%

Allerdings muss ich an dieser Stelle auf etwas hinweisen, da die eingebauten Zeitfunktionen, wie ich bereits erwähnt habe, nicht gut dafür geeignet sind, abstrakte Dauern zu behandeln. Ich werde die .tickFormat ändern, um auch die Stunden anzuzeigen:

%Vor%

Sehen Sie sich das JSFiddle dessen an, was das Ergebnis sein könnte ...

Je nachdem, wo Sie sich auf der Welt befinden, erhalten Sie einen anderen Wert für den Stundenort. Ich bin an der Ostküste der USA, also sagt mein Stundenort 19 . Woher kommt das? Sollte es nicht Null sein?

Nun, leider, als wir den Bereich der Skala von 0 auf die Anzahl der Millisekunden des größten Datenwerts verschoben haben, hat er regelmäßig Date -Objekte erstellt, die diese Werte für die Millisekunden-Eingabe verwenden. Dies bedeutet, dass sie die Anzahl der Millisekunden seit Mitternacht UTC am 1. Januar 1970 repräsentieren. Hier in der Eastern-Zeitzone der USA war es am 31. Dezember 1969 19:00:00. Hier kommt die 19 her oder welchen anderen Wert Sie auch bekommen.

Wenn Sie wissen, dass alle Ihre Daten weniger als 1 Stunde sind, können Sie das vielleicht einfach ignorieren. Wenn Sie einen Stundenplatz verwenden müssen, können Sie dies umgehen, indem Sie erzwingen, dass d3 die UTC-Zeit verwendet, um die Achse mit d3.time.format.utc() :

zu formatieren %Vor%

Hier ist das JSFiddle , das zur Verwendung von UTC aktualisiert wurde.

Jetzt können Sie sehen, dass die Stunde wie erwartet 0 ist.

Wenn Ihre Daten länger als 24 Stunden sind, funktioniert diese Methode natürlich nicht. Sie müssen die Achse wie in Option 1 manuell ausführen .

Hoffentlich hilft Ihnen das zumindest beim Einstieg, es ist jedoch ein kniffliges Problem, und es scheint keine elegante Lösung zu geben, die in die Bibliothek eingebaut wird, um damit umzugehen. Vielleicht würde es eine gute Feature-Anfrage auf dem Git Repo von d3 machen. Ich würde gerne hören, ob @mbostock irgendwelche Vorschläge hat, wie man mit abstrakten Zeitdauern in d3 umgeht, ohne an Date -Objekte gebunden zu sein, die Verweise auf absolute Zeitpunkte benötigen.

    
jshanley 03.07.2014, 02:36
quelle

Tags und Links