In diesem Artikel möchte ich Sie durch ein Beispielprojekt führen, das ich kürzlich erstellt habe - ein völlig originales -Sputzentyp mithilfe der D3 -Bibliothek, in der zeigt, wie jede dieser Komponenten dazu addiert, D3 zu machen Eine großartige Bibliothek zu lernen.
d3 steht für datengesteuerte Dokumente. Es handelt sich um eine JavaScript -Bibliothek, mit der alle möglichen wundervollen Datenvisualisierungen und -diagramme erstellt werden können.
Wenn Sie jemals eine der fabelhaften interaktiven Geschichten aus der New York Times gesehen haben, werden Sie D3 bereits in Aktion gesehen haben. Sie können auch einige coole Beispiele für großartige Projekte sehen, die hier mit D3 gebaut wurden.
Die Lernkurve ist ziemlich steil für den Einstieg mit der Bibliothek, da D3 ein paar spezielle Macken hat, die Sie wahrscheinlich zuvor noch nicht gesehen haben. Wenn Sie jedoch die erste Phase des Lernens von D3 überschreiten können, um gefährlich zu sein, können Sie bald in der Lage sein, wirklich coole Sachen für sich selbst zu erstellen.
Es gibt drei Hauptfaktoren, die D3 wirklich von allen anderen Bibliotheken abheben:
Als Wirtschaftswissenschaftler im College war ich immer an Einkommensungleichheit interessiert. Ich nahm ein paar Klassen zu diesem Thema und es fiel mir als etwas an, das nicht vollständig in dem Maße verstanden wurde, in dem es sein sollte.
Ich habe angefangen, die Einkommensungleichheit mithilfe von Googles öffentlichem Data Explorer zu untersuchen…
Wenn Sie sich auf die Inflation einstellen, ist das Haushaltseinkommen für die unteren 40% der Gesellschaft ziemlich konstant , obwohl die Produktivität von pro Arbeiter in die Höhe geschossen hat. Es war erst wirklich die Top 20%, die mehr von den Vorteilen erzielt haben (und innerhalb dieser Halterung ist der Unterschied noch schockierender, wenn Sie sich die Top 5%ansehen).
Hier war eine Nachricht, die ich auf überzeugende Weise vermitteln wollte, was eine perfekte Gelegenheit bot, einige D3.Js zu verwenden, also habe ich angefangen, ein paar Ideen zu skizzieren.
Da wir mit D3 arbeiten, könnte ich mehr oder weniger einfach anfangen, absolut alles zu skizzieren, an das ich denken könnte. Ein einfaches Zeilendiagramm, ein Balkendiagramm oder ein Blasendiagramm wäre einfach genug gewesen, aber ich wollte etwas anderes machen.
Ich finde, dass die häufigste Analogie, die die Menschen als Gegenargument für Bedenken hinsichtlich der Ungleichheit nutzten, "Wenn der Kuchen größer wird, dann gibt es noch mehr zu gehen". Die Intuition lautet, dass, wenn der Gesamtanteil des BIP schafft, um einen großen Teil zu erhöhen, selbst wenn einige Leute eindünneres Stück Kuchen erhalten, werden sie immer noch besser fern besser dran,
. Wie wir jedoch sehen können, ist es für den Kuchen absolut möglich, größereund
zu werden, damit die Leute insgesamt weniger davon bekommen.
Meine erste Idee zur Visualisierung dieser Daten sah ungefähr so aus:
Die Idee wäre, dass wir dieses pulsierende Kreisdiagramm haben würden, wobei jede Scheibe ein Fünftel der US -Einkommensverteilung darstellt. Die Fläche jedes Kuchenscheibens würde sich darauf beziehen, wie viel Einkommen dieses Segments der Bevölkerung einnimmt, und die Gesamtfläche des Diagramms würde sein Gesamt -BIP darstellen.
Ich bin jedoch bald auf ein Problem gestoßen. Es stellt sich heraus, dass das menschliche Gehirn in der Größe der verschiedenen Bereiche außergewöhnlich schlecht ist. Als ich dies konkreter kartierte, war die Nachricht nicht annähernd so offensichtlich, wie sie hätte sein sollen:
Hier sieht es tatsächlich so aus, als würden die ärmsten Amerikaner im Laufe der Zeit
reicher, was bestätigt, was intuitiv wahr zu sein scheint. Ich dachte noch mehr über dieses Problem nach, und meine Lösung bestand darin, den Winkel jeder Bogen konstant zu halten, wobei sich der Radius jedes Bogens dynamisch änderte.
So sah dies in der Praxis aus:
Ich möchte darauf hinweisen, dass dieses Bild hier immer noch dazu neigt, den Effekt zu unterschätzen. Der Effekt wäre offensichtlicher gewesen, wenn wir ein einfaches Balkendiagramm verwendet hätten:
Ich war jedoch entschlossen, eine einzigartige Visualisierung vorzunehmen, und ich wollte diese Nachricht nach Hause hämmern, dass der pie größere erhalten kann, während ein teilen davon kann kleinere erhalten. Jetzt, wo ich meine Idee hatte, war es Zeit, sie mit D3 zu bauen.
Jetzt, wo ich weiß, was ich bauen werde, ist es Zeit, in das wahre Fleisch dieses Projekts einzusteigen und zu beginnen, ein Code zu schreiben .
Vielleicht denken Sie, dass ich damit beginnen würde, meine ersten Codezeilen von Grund auf neu zu schreiben, aber Sie würden sich irren. Dies ist D3, und da wir mit D3 arbeiten, können wir immer einen vorgeschriebenen Code von der Community finden, um uns zu starten.
Wir erstellen etwas völlig Neues, aber es hat viel mit einem regulären Kreisdiagramm zu tun, also habe ich mich kurz auf Bl.ocks.org angesehen und mich für diese klassische Implementierung von Mike Bostock entschieden. Einer der Schöpfer von D3. Diese Datei wurde wahrscheinlich schon tausend Male kopiert, und der Typ, der sie geschrieben hat
Diese Datei ist in D3 V3 geschrieben, das jetzt zwei Versionen veraltet ist, da Version 5 schließlich letzten Monat veröffentlicht wurde. Eine große Änderung in D3 V4 war, dass die Bibliothek in einen flachen Namespace umgestellt wurde, sodass diese Skalierungsfunktionen wie d3.scale.ordinal () stattdessen wie d3.ScaleOrn () geschrieben werden. In Version 5 war die größte Änderung, dass Datenladungsfunktionen jetzt als Versprechen strukturiert sind, was es einfacher macht, mehrere Datensätze gleichzeitig zu verarbeiten.Um Verwirrung zu vermeiden, habe ich mich bereits die Mühe gemacht, eine aktualisierte V5 -Version dieses Codes zu erstellen, die ich auf blockbuilder.org gespeichert habe. Ich habe auch die Syntax so konvertiert, dass sie mit ES6 -Konventionen passen, z.
Hier ist was wir bereits beginnen:
Ich habe diese Dateien dann in mein Arbeitsverzeichnis kopiert und dafür gesorgt, dass ich alles auf meinem eigenen Computer replizieren konnte. Wenn Sie dieses Tutorial selbst folgen möchten, können Sie dieses Projekt aus unserem Github -Repo klonen. Sie können mit dem Code in der Datei starter.html beginnen. Bitte beachten Sie, dass Sie einen Server (wie diesen) benötigen, um diesen Code auszuführen, da er unter der Haube auf der Fetch -API angewiesen ist, um die Daten abzurufen.
Lassen Sie mich Ihnen einen kurzen Überblick darüber geben, wie dieser Code funktioniert.
durch unseren Code gehen
Dies macht unseren Code super wiederverwendbar, da wir ihn jemals größer oder kleiner machen möchten, müssen wir uns nur um diese Werte machen.
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Als nächstes geben wir eine SVG -Leinwand an den Bildschirm an. Wenn Sie nicht viel über SVGs wissen, können Sie über die Leinwand als den Speicherplatz auf der Seite nachdenken, auf dem wir Formen zeichnen können. Wenn wir versuchen, ein SVG außerhalb dieses Bereichs zu zeichnen, wird es einfach nicht auf dem Bildschirm angezeigt:
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Wir ergreifen einen leeren DIV mit der ID der Chart-Fläche mit einem Anruf bei D3.Select (). Wir haben auch eine SVG -Leinwand mit der Methode d3.Append () an und setzen einige Abmessungen für die Breite und Höhe mit der Methode d3.Attr () fest.
Wir haben auch ein SVG -Gruppenelement an dieser Leinwand angehängt, was eine spezielle Art von Element ist, mit der wir Elemente miteinander strukturieren können. Dies ermöglicht es uns, unsere gesamte Visualisierung in die Mitte des Bildschirms zu verlagern, indem wir das Transformationsattribut des Gruppenelements verwenden.
Danach richten wir eine Standardskala ein, mit der wir für jedes Stück unseres Kuchens eine neue Farbe zuweisen werden:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Als nächstes haben wir ein paar Zeilen, in denen das Pie -Layout von D3 eingerichtet ist:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
In D3 sind Layouts spezielle Funktionen, die wir auf einen Datensatz aufrufen können. Eine Layoutfunktion nimmt ein Array von Daten in einem bestimmten Format auf und spuckt ein transformiertes Array mit einigen automatisch erzeugten Werten aus, mit denen wir dann etwas tun können.
Wir müssen dann einen Pfadgenerator definieren, mit dem wir unsere Bögen zeichnen können. Mit Pfadgeneratoren können wir Pfad -SVGs in einem Webbrowser zeichnen. Alles, was D3 wirklich tut, ist, Datenstücke mit Formen auf dem Bildschirm zu assoziieren, aber in diesem Fall möchten wir eine kompliziertere Form definieren als nur einen einfachen Kreis oder Quadrat. Pfad -SVGs funktioniert, indem eine Route definiert wird, in der eine Linie gezogen wird, die wir mit ihrem D -Attribut definieren können.
So könnte dies aussehen:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Das D -Attribut enthält eine spezielle Codierung, mit der der Browser den gewünschten Pfad zeichnen kann. Wenn Sie wirklich wissen möchten, was diese Zeichenfolge bedeutet, können Sie in der SVG -Dokumentation von MDN darüber erfahren. Für die Programmierung in D3 müssen wir nichts über diese besondere Codierung wissen, da wir Generatoren haben, die unsere D -Attribute für uns ausspucken, die wir nur mit einigen einfachen Parametern initialisieren müssen.
Für einen Bogen müssen wir unserem Pfadgenerator einen Innerradius und einen Außenradius -Wert in Pixel geben, und der Generator sortiert die komplexen Mathematik aus, die in die Berechnung jeder der Winkel für uns berechnet werden:
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Für unser Diagramm verwenden wir einen Wert von Null für unseren Innerradius, der uns ein Standardkreisdiagramm gibt. Wenn wir jedoch stattdessen ein Donut -Diagramm zeichnen wollten, müssten wir nur einen Wert anschließen, der kleiner als unser äußerer Wert ist.
Nach ein paar Funktionserklärungen laden wir unsere Daten mit der Funktion d3.json ():
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
In D3 Version 5.x gibt ein Aufruf an d3.json () ein Versprechen zurück, was bedeutet, dass D3 den Inhalt der JSON -Datei abruft, die sie auf dem relativ Wir rufen die dann () -Methode an, sobald sie geladen wurde. Wir haben dann Zugriff auf das Objekt, das wir im Datenargument unseres Rückrufs betrachten.
Wir übergeben hier auch eine Funktionsreferenz - Typ -, die alle Werte, die wir in Zahlen laden, umwandeln, mit denen wir später arbeiten können:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Wenn wir eine Konsole.log (Daten) hinzufügen; Erklärung an die Spitze unseres D3.json -Rückrufs, wir können uns die Daten ansehen, mit denen wir jetzt arbeiten:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Unsere Daten werden hier in zwei verschiedene Arrays aufgeteilt, die unsere Daten für Äpfel bzw. Orangen darstellen.
Mit dieser Zeile werden wir die Daten wechseln, die wir ansehen, wenn eine unserer Optionsfelder klickt:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Wir müssen auch die Funktion update () auf dem ersten Lauf unserer Visualisierung aufrufen und einen Anfangswert (mit unserem "Äpfel -Array) übergeben.
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Schauen wir uns an, was unsere Update () -Funktion macht. Wenn Sie neu in D3 sind, kann dies zu Verwirrung führen, da es einer der schwierigsten Teile von D3 ist, um zu verstehen ...
<span>const arc = d3.arc() </span> <span>.innerRadius(0) </span> <span>.outerRadius(radius); </span>
Erstens verwenden wir einen Standardfunktionsparameter für Wert. Wenn wir ein Argument an unsere Funktion update () übergeben (wenn wir sie zum ersten Mal ausführen), werden wir diese Zeichenfolge verwenden, oder sonst erhalten wir den Wert, den wir vom Klickereignis gewünscht haben Unsere Funkeingänge.
Wir verwenden dann das allgemeine Update -Muster in D3, um das Verhalten unserer Bögen zu bewältigen. Dies beinhaltet normalerweise die Ausführung eines Datenverbindungen, des Verlassens der alten Elemente, der Aktualisierung vorhandener Elemente auf dem Bildschirm und dem Hinzufügen neuer Elemente, die zu unseren Daten hinzugefügt wurden. In diesem Beispiel müssen wir uns keine Sorgen um das Verlassen von Elementen machen, da wir immer die gleiche Anzahl von Kuchenscheiben auf dem Bildschirm haben.
Zuerst sind unsere Daten miteinander verbunden:
d3<span>.json("data.json", type).then(data => { </span> <span>// Do something with our data </span><span>}); </span>
virtuelle Auswahl aller Bögen auf dem Bildschirm.
Als nächstes aktualisieren wir alle SVGs auf dem Bildschirm, die in unserem Datenarray noch vorhanden sind. Wir fügen hier einen Übergang hinzu - eine fantastische Funktion der D3 -Bibliothek -, um diese Updates über 200 Millisekunden zu verbreiten:<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Wir verwenden die Antrkter -Methode () auf dem Aufruf von D3.Transition (), um einen benutzerdefinierten Übergang zu definieren, mit dem D3 die Positionen der einzelnen Bögen aktualisieren sollte (Übergang mit dem D -Attribut). Wir müssen dies nicht tun, wenn wir versuchen, einen Übergang zu den meisten unserer Attribute hinzuzufügen, aber wir müssen dies für den Übergang zwischen verschiedenen Pfaden tun. D3 kann nicht wirklich herausfinden, wie man zwischen benutzerdefinierten Pfaden wechselt. Daher verwenden wir die Funktion arctween (), um D3 zu informieren, wie jeder unserer Pfade zu jedem Zeitpunkt gezogen werden sollte.
So sieht diese Funktion aus:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Wir verwenden d3.Interpolat () hier, um einen sogenannten Interpolator zu erstellen. Wenn wir die Funktion nennen, die wir in der I -Variablen mit einem Wert zwischen 0 und 1 speichern, erhalten wir einen Wert, der irgendwo zwischen diesem liegt. In diesem Fall ist dies._Current ein Objekt, das den Start- und Endwinkel der Kuchenscheibe enthält, die wir betrachten, und A repräsentiert den neuen Datenpunkt, auf den wir aktualisieren.
Sobald wir den Interpolator einrichten haben, aktualisieren wir den Wert this._current, um den Wert zu enthalten, den wir am Ende haben (i (a)), und dann geben wir eine Funktion zurück, die berechnet wird Der Pfad, den unser Bogen enthalten sollte, basierend auf diesem t -Wert. Unser Übergang wird diese Funktion auf jeder Tick seiner Uhr ausführen (in einem Argument zwischen 0 und 1), und dieser Code bedeutet, dass unser Übergang zu jedem Zeitpunkt weiß, wo unsere Bögen gezogen werden sollen.
Schließlich muss unsere Funktion update () neue Elemente hinzufügen, die nicht im vorherigen Datenarray waren:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Dieser Codeblock setzt die Anfangspositionen jeder unserer Bögen, das erste Mal, dass diese Aktualisierungsfunktion ausgeführt wird. Die Methode Enter () gibt uns hier alle Elemente in unseren Daten, die dem Bildschirm hinzugefügt werden müssen. Anschließend können wir jedes dieser Elemente mit den ATTR () -Methoden überschreiten, um die Füllung und Position jedes unserer einzelnen zu setzen Bögen. Wir geben jedem unserer Bögen auch einen weißen Grenze, wodurch unser Diagramm ein wenig ordentlich aussieht. Schließlich setzen wir die this._current -Eigenschaft jedes dieser Bögen als Anfangswert des Elements in unseren Daten ein, den wir in der Funktion "ARCTween () () verwenden.
Machen Sie sich keine Sorgen, wenn Sie nicht genau befolgen können, wie dies funktioniert, da es sich um ein ziemlich fortgeschrittenes Thema in D3 handelt. Das Tolle an dieser Bibliothek ist, dass Sie nicht all seine inneren Arbeiten kennen müssen, um ein paar leistungsstarke Dinge damit zu erstellen. Solange Sie die Bits verstehen können, die Sie ändern müssen, ist es in Ordnung, einige der Details abstrahieren, die nicht vollständig wesentlich sind.
Das bringt uns zum nächsten Schritt im Prozess…
Jetzt, da wir einen Code in unserer lokalen Umgebung haben und wir verstehen, was es tut, werde ich die Daten ausschalten, die wir uns ansehen, damit es mit den Daten funktioniert, an denen wir interessiert sind .
Ich habe die Daten aufgenommen, mit denen wir im Daten/ Ordner unseres Projekts zusammenarbeiten werden. Da sich diese neue Datei in CSV -Format in einem CSV -Format befindet (es ist die Art von Datei, die Sie mit Microsoft Excel öffnen können), werde ich die Funktion d3.csv () anstelle des D3.json verwenden (D3.json ( ) Funktion:
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Diese Funktion macht im Grunde dasselbe wie d3.json () - und konvertiert unsere Daten in ein Format, das wir verwenden können. Ich entferne auch die Funktion type () initializer als zweites Argument hier, da dies für unsere alten Daten spezifisch war.
Wenn Sie eine Anweisung von Console.log (Daten) oben im D3.CSV -Rückruf hinzufügen, können Sie die Form der Daten sehen, mit denen wir arbeiten:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Wir haben eine Reihe von 50 Elementen, wobei jedes Element ein Jahr in unseren Daten darstellt. Für jedes Jahr haben wir dann ein Objekt mit Daten für jede der fünf Einkommensgruppen sowie einige andere Felder. Wir könnten hier für eines dieser Jahre ein Kreisdiagramm erstellen, aber zuerst müssen wir unsere Daten ein wenig umgehen, damit es im richtigen Format ist. Wenn wir einen Daten schreiben möchten, verbinden wir mit D3 ein Array, wobei jedes Element an eine SVG gebunden ist.
Erinnern Sie sich daran, dass wir in unserem letzten Beispiel ein Array mit einem Gegenstand für jede Kuchenscheibe hatten, die wir auf dem Bildschirm anzeigen wollten. Vergleichen Sie dies mit dem, was wir im Moment haben, was ein Objekt mit den Schlüssel von 1 bis 5 ist, die jede Kuchenscheibe darstellen, die wir zeichnen wollen.
Um dies zu beheben, füge ich eine neue Funktion namens Prepectata () hinzu, um die zuvor von uns geladene Art () -Funktion zu ersetzen, die wir über jedes Element unserer Daten iterieren:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Für jedes Jahr gibt diese Funktion ein Objekt mit einem Wertearray zurück, das wir in unsere Datenverbindung übergeben. Wir kennzeichnen jeden dieser Werte mit einem Namensfeld und geben ihnen einen numerischen Wert, der auf den Einkommenswerten basiert, die wir bereits hatten. Wir verfolgen auch das durchschnittliche Einkommen in jedem Jahr zum Vergleich.
Zu diesem Zeitpunkt haben wir unsere Daten in einem Format, mit dem wir arbeiten können:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Ich werde zunächst ein Diagramm für das erste Jahr in unseren Daten generieren, und dann werde ich mir Sorgen machen, es für den Rest der Jahre zu aktualisieren.
Im Moment beginnt unsere Daten im Jahr 2015 und endet im Jahr 1967, sodass wir dieses Array umkehren müssen, bevor wir etwas anderes tun:
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Im Gegensatz zu einem normalen Kreisdiagramm möchten wir für unser Diagramm die Winkel jeder unserer Bögen reparieren und nur die Änderung der Radius durch unsere Visualisierungsaktualisierungen durchführen. Dazu ändern wir die Value () -Methode in unserem Kuchenlayout, so dass jeder Kuchenscheiben immer die gleichen Winkel erhält:
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Als nächstes müssen wir unseren Radius jedes Mal aktualisieren, wenn unsere Visualisierungsaktualisierungen. Dazu müssen wir eine Skala erstellen, die wir verwenden können. Eine Skala ist eine Funktion in D3, die ein Eingabe zwischen zwei Werten nimmt, die wir als Domäne übergeben, und dann ein Ausgangs zwischen zwei verschiedenen Werten ausspuckt, die wir darin übergeben als Reichweite. Hier ist die Skala, die wir verwenden werden:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Wir fügen diese Skala hinzu, sobald wir Zugriff auf unsere Daten haben, und wir sagen, dass unsere Eingabe zwischen 0 und dem größten Wert in unserem Datensatz liegen sollte, was das Einkommen der reichsten Gruppe im letzten Jahr ist in unseren Daten (Daten [49]. Werte [4] .Value). Für die Domäne stellen wir das Intervall fest, dass unser Ausgangswert zwischen.
liegen sollte.Dies bedeutet, dass eine Eingabe von Null uns einen Pixelwert von Null ergeben sollte, und eine Eingabe des größten Werts in unseren Daten sollte uns einen Wert von der Hälfte unserer Breite oder Höhe geben - je nachdem, welcher Wert kleiner ist.
Beachten Sie, dass wir hier auch eine Quadratwurzelskala verwenden. Der Grund, warum wir dies tun, ist, dass wir möchten, dass der Bereich unserer Kuchenscheiben eher zum Einkommen jeder unserer Gruppen als zum Radius ist. Da Fläche = πr 2 , müssen wir eine Quadratwurzelskala verwenden, um dies zu berücksichtigen.
Wir können diese Skala dann verwenden, um den äußerenradius -Wert unseres ARC -Generators in unserer Funktion update () zu aktualisieren:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Wenn sich unsere Daten ändert, wird der Radiuswert bearbeitet, den wir für jedes unserer Bögen verwenden möchten.
Wir sollten unseren Anruf auch nach äußerlich entfernen, wenn wir unseren ARC -Generator anfänglich einrichten, damit wir dies nur ganz oben in unserer Datei haben:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Schließlich müssen wir ein paar Änderungen zu dieser Update () -Funktion vornehmen, damit alles mit unseren neuen Daten übereinstimmt:
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Da wir unsere Optionspunkte nicht mehr verwenden werden, überschreite ich nur im Jahr-Objekt, das wir verwenden möchten, indem wir anrufen:
<span>const arc = d3.arc() </span> <span>.innerRadius(0) </span> <span>.outerRadius(radius); </span>
Schließlich werde ich den Ereignishörer entfernen, den wir für unsere Formulareingänge festlegen. Wenn alles in Planung gegangen ist, sollten wir für das erste Jahr in unseren Daten ein wunderschön aussehendes Diagramm haben:
Der nächste Schritt besteht darin, unseren Visualisierungszyklus zwischen verschiedenen Jahren zu haben und zeigt, wie sich das Einkommen im Laufe der Zeit verändert hat. Wir werden dies tun, indem wir den Anruf in die SetInterval () -Funktion von JavaScript hinzufügen, mit der wir einen wiederholten Code ausführen können:
d3<span>.json("data.json", type).then(data => { </span> <span>// Do something with our data </span><span>}); </span>
Wir setzen einen Timer in dieser Zeitvariable ein, und alle 200 ms werden dieser Code die Funktion Step () ausführen, die unser Diagramm auf die Daten des nächsten Jahres aktualisiert und den Timer um 1 erhöht. Wenn der Timer ist zu einem Wert von 49 (dem letzten Jahr in unseren Daten), es wird sich selbst zurücksetzen. Dies gibt uns jetzt eine schöne Schleife, die kontinuierlich laufen wird:
, um die Dinge etwas nützlicher zu machen. Ich werde auch einige Etiketten hinzufügen, die uns die rohen Figuren geben. Ich ersetze den gesamten HTML -Code im Gremium unserer Datei durch:
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Wir strukturieren unsere Seite hier mit dem Grid -System von Bootstrap, mit dem wir unsere Seitenelemente in Kästchen ordentlich formatieren können.
Ich werde das alles mit JQuery aktualisieren, wenn sich unsere Daten ändert:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Ich werde auch ein paar Änderungen an den CSS oben in unserer Datei vornehmen, die uns eine Legende für jedes unserer Bögen geben und auch unsere Überschrift zentrieren:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Was wir am Ende haben, ist etwas ziemlich Präsentierbares:
Da es ziemlich schwierig ist zu sehen, wie sich diese Bögen hier im Laufe der Zeit verändert haben, möchte ich einige Grid -Linien hinzufügen, um zu zeigen, wie die Einkommensverteilung im ersten Jahr unserer Daten aussah:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Ich verwende die Methode Array.foreach (), um dies zu erreichen, obwohl ich auch mit D3s üblichem Allgemeines Update -Muster vergehen kann (Join/Exit/Update/Eingabetaste).
Ich möchte auch eine Linie hinzufügen, um das durchschnittliche Einkommen in den USA zu zeigen, das ich jedes Jahr aktualisieren werde. Zunächst füge ich zum ersten Mal die durchschnittliche Zeile hinzu:
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Dann werde ich dies am Ende unserer Update () -Funktion aktualisieren, wenn sich das Jahr ändert:
<span>const arc = d3.arc() </span> <span>.innerRadius(0) </span> <span>.outerRadius(radius); </span>
Ich sollte beachten, dass es für uns wichtig ist, jeden dieser Kreise nach unserem ersten Aufruf zum Update () hinzuzufügen, da sie sonst zwischen jeweils wiedergegeben werden Unsere ARC-Pfade (SVG-Schichten werden durch die Reihenfolge bestimmt, in der sie dem Bildschirm hinzugefügt werden, und nicht durch ihre Z-Index).
Zu diesem Zeitpunkt haben wir etwas, das die Daten vermittelt, mit denen wir etwas klarer arbeiten:
-Spiele/Pause -Taste sowie einen Jahrschieberegler hinzufügen, sodass der Benutzer ein bestimmtes Datum auswählen kann.
Hier ist das HTML, mit dem ich diese Elemente auf dem Bildschirm hinzufügt:
d3<span>.json("data.json", type).then(data => { </span> <span>// Do something with our data </span><span>}); </span>
Zuerst möchte ich das Verhalten unserer
spiele/pause definieren. Wir müssen den Code, den wir früher für unser Intervall geschrieben haben, ersetzen, damit wir den Timer mit der Taste starten können. Ich gehe davon aus, dass die Visualisierung in einem "Pause" beginnt und dass wir diese Taste drücken müssen, um die Dinge zu starten.
<span>const width = 540; </span><span>const height = 540; </span><span>const radius = Math.min(width, height) / 2; </span>
Wenn unsere Schaltfläche klickt, wird unser If/sonst -Block hier ein anderes Verhalten definieren, je nachdem, ob unsere Schaltfläche eine Schaltfläche „Spielen“ oder eine Schaltfläche „Pause“ ist. Wenn auf der Schaltfläche, auf die wir klicken, lautet "Spielen", wechseln wir die Schaltfläche auf eine "Pause" -Taste und beginnen unsere Intervallschleife. Wenn die Schaltfläche eine Schaltfläche "Pause" ist, ändern wir den Text in "Spielen" und verwenden die Funktion clearInterval (), um die Schleife vom Ausführen zu verhindern.
Für unseren Schieberegler möchte ich den Schieberegler verwenden, der mit der Jquery UI -Bibliothek geliefert wird. Ich füge dies in unser HTML ein und werde ein paar Zeilen schreiben, um dies dem Bildschirm hinzuzufügen:
<span>const svg = d3.select("#chart-area") </span> <span>.append("svg") </span> <span>.attr("width", width) </span> <span>.attr("height", height) </span> <span>.append("g") </span> <span>.attr("transform", <span>`translate(<span>${width / 2}</span>, <span>${height / 2}</span>)`</span>); </span>
Hier verwenden wir die Folienoption, um einen Ereignishörer an den Schieberegler anzubringen. Immer wenn unser Schieberegler auf einen anderen Wert verschoben wird, aktualisieren wir unseren Timer auf diesen neuen Wert und führen in unseren Daten in diesem Jahr unsere Funktion update () aus.
.Wir können diese Zeile am Ende unserer Update () -Funktion hinzufügen, sodass unser Schieberegler zum richtigen Jahr weitergeht, wenn unsere Schleife ausgeführt wird:
<span>const color = d3.scaleOrdinal(["#66c2a5", "#fc8d62", "#8da0cb","#e78ac3", "#a6d854", "#ffd92f"]); </span>
Ich füge auch eine Zeile zu unserer Funktion updateHTML () hinzu (die ausgeführt wird, wenn sich unsere Visualisierung ändert), die den Wert des Etiketts basierend auf dem aktuellen Jahr in den Daten anpassen kann:
<span>const pie = d3.pie() </span> <span>.value(d => d.count) </span> <span>.sort(null); </span>
Ich werde noch ein paar Zeilen in unser CSS einwerfen, damit alles ein wenig ordentlicher aussieht:
<span><span><span><svg</span> width<span>="190"</span> height<span>="160"</span>></span> </span> <span><span><span><path</span> d<span>="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"</span> stroke<span>="black"</span> fill<span>="transparent"</span>/></span> </span><span><span><span></svg</span>></span> </span>
Und da haben wir es - unser fertiges Produkt - eine voll funktionsfähige interaktive Datenvisualisierung, wobei alles wie erwartet funktioniert.
Hoffentlich hat dieses Tutorial die wahre Kraft von D3 gezeigt, sodass Sie absolut alles erstellen können, was Sie sich vorstellen können.
Beginn mit D3 von Grund auf ist immer ein schwieriger Prozess, aber die Belohnungen sind es wert. Wenn Sie lernen möchten, wie Sie eigene visuelle Visualisierungen erstellen möchten, finden Sie hier einige Online -Ressourcen, die Sie möglicherweise hilfreich finden:
Und vergessen Sie nicht, wenn Sie die fertige Version des Codes sehen möchten, den ich im Artikel verwendet habe, können Sie ihn in unserem Github -Repo finden.
Kann ich D3 für große Datensätze verwenden? Ja, D3 kann große und komplexe Datensätze umgehen. Es verfügt über leistungsstarke Datenmanipulationsfunktionen, mit denen Sie in jedem Format mit Daten arbeiten können. D3 verfügt außerdem über integrierte Funktionen zum Laden von Daten aus verschiedenen Quellen, um die Integration in Ihre vorhandene Dateninfrastruktur zu vereinfachen.
Ist D3 für die Visualisierung von Echtzeitdaten geeignet? ist gut geeignet für die Echtzeit-Datenvisualisierung. Es verfügt über einen flexiblen Daten -Update -Mechanismus, mit dem Sie Ihre Visualisierungen nach dem Eintauchen neuer Daten einfach aktualisieren können. Dadurch ist D3 eine großartige Wahl für Anwendungen wie Dashboards oder Live -Daten -Feeds.
Es stehen viele Ressourcen zum Lernen D3 zur Verfügung. Die offizielle D3 -Website verfügt über eine Fülle von Dokumentationen und Beispielen, und es gibt zahlreiche Online -Tutorials und Kurse, die D3 ausführlich abdecken. Praxis ist auch der Schlüssel - je mehr Sie D3 verwenden, desto komfortabler werden Sie mit seinen Konzepten und API.
Das obige ist der detaillierte Inhalt vonInteraktive Datenvisualisierung mit modernem JavaScript und D3. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!