Data Driven Documents (D3.js) este o bibliotecă JavaScript utilizată pentru a crea vizualizări de date folosind HTML, CSS și SVG. Face acest lucru legând datele de DOM (Document Object Model) și elementele sale și permițându-le să se transforme atunci când datele se schimbă.

De exemplu, să presupunem că vrem să creăm o diagramă circulară cu cantități de cărți din fiecare gen dintr-o bibliotecă. Avem câteva date pe care le actualizăm de fiecare dată când un bibliotecar intră într-o carte nouă. Îl stocăm în starea aplicației, într-o variabilă numită „cărți”.

const [books, setBooks] = useState(initialBooks)
const initialBooks = [
    {
        name: "Harry Potter and the Philosophers Stone",
        author: "J. K. Rowling",
        genre: "fantasy"
    },{
        name: "The Pedagogy of Freedom",
        author: "Bell hooks",
        genre: "non-fiction"
    },{
        name: "Harry Potter and the Chamber of Secrets",
        author: "J. K. Rowling",
        genre: "fantasy"
    },{
        name: "Gilgamesh",
        author: "Derrek Hines",
        genre: "poetry"
    }
]

În acest moment am putea crea un grafic care conține 50% fantezie, 25% non-ficțiune și 25% poezie. Când bibliotecarul adaugă o carte nouă în baza de date, datele se schimbă și grefa ta se schimbă. Să presupunem că adăugăm „50 de preparate vegane”.

setBooks(books.concat(
    {
        name: "50 vegan dishes",
        author: "Antti Leppänen",
        genre: "non-fiction"
    }
))

Când aceste date se modifică, graficul nostru D3 actualizează DOM pentru a se potrivi cu noile date. Acum avem 40% fantezie, 40% non-ficțiune și 20% poezie. D3 facilitează manipularea site-ului web DOM. Aceasta înseamnă că îl puteți utiliza pentru a crea, actualiza și șterge elemente din structura paginii.

Dacă doriți să urmați împreună cu acest exemplu, puteți utiliza Creați aplicația React pentru a crea o aplicație web simplă React. Dacă React îți este încă necunoscut, poți consultați acest tutorial din documentația React.

  1. Creați o aplicație nouă, numită my-d4-app npx create-react-app my-d3-app. Schimbați directorul în folderul creat utilizând cd my-d3-app.
  2. Instalați D3 rulând npm install d3 --save .
  3. Importați D3 în App.js adăugând import * as d3 from d3 . Trebuie să utilizați import * („importați totul”) deoarece D3 nu are un modul implicit exportat.

Selectarea elementelor DOM

D3 facilitează manipularea DOM. De exemplu, să încercăm să le schimbăm pe toate <p&gt;

-elemente pentru a avea un stil inline setând culoarea la albastru.

d3.selectAll("p").style("color", "blue")

.selectAll()-metoda ne permite să selectăm toate elementele unui anumit tip. Putem folosi și .select() pentru a selecta noduri individuale.

Biblioteca React manipulează și DOM. Aceasta înseamnă că trebuie să depunem un efort suplimentar pentru ca acesta să funcționeze împreună cu D3. Din fericire, React are deja o soluție pentru a permite direcționarea și actualizarea elementelor DOM. Pentru a face acest lucru, React folosește referințe.

Să creăm un <div>-elementează și adaugă o referință la acesta, apoi folosește referința pentru a o prelua cu D3.

d3.select(this.refs.myDiv).style(“background-color”, “blue”)
render(<div ref=”myDiv”></div>)

Adăugarea de elemente la DOM

După ce ați selectat elementul pe care doriți să îl manipulați, puteți începe să adăugați mai multe elemente la acesta. De exemplu, imaginați-vă că avem un <ol ref="myList">. Putem folosi D3 pentru a adăuga un nou element de listă, care conține textul „banane”.

d3.select(this.refs.myList)
    .append("li")
    .text("bananas")

Folosirea datelor pentru a crea

Puteți face D3 conștient de datele dvs. selectând elemente DOM și atașând datele la acestea folosind .data(). D3 are o metodă numită .enter(), care este adesea folosit pentru lucrul cu date. Înseamnă că aceste elemente de date trebuie adăugate la DOM. Intră în contrapartidă, .exit() , este folosit pentru a semnifica acele elemente care nu mai există în date, dar există în DOM. Îl putem folosi pentru a elimina acele elemente împreună cu remove, ca în .exit().remove().

Să aruncăm o privire la un exemplu.

import React, { component } from 'react'
import * as d3 from 'd3'
class App extends Component {
    const temperatureData = [ 8, 5, 13, 9, 12 ]
    d3.select(this.refs.temperatures)
        .selectAll("h2")
        .data(temperatureData)
        .enter()
            .append("h2")
            .text("New Temperature")
 
    render(<div ref="temperatures"></div>)
}
export default App

Se citește „D3, selectați elementul cu referință„ temperaturi ”. Apoi, atașați temperatureData la acesta <h2>-elemente. Pentru părțile de date care nu sunt încă reprezentate în DOM, adăugați nou <h2>-element cu textul „Temperatură nouă”.

Așteptați, acum scrie „Temperatură nouă” din nou și din nou! Ce se întâmplă dacă dorim să afișăm valoarea reală a punctului de date?

Proprietăți ca funcții

În D3, stilurile, atributele și alte proprietăți ale elementelor pot fi setate folosind funcții. Să refactorizăm codul de mai sus pentru a utiliza o funcție care setează textele fișierului <h2> -elemente la valoarea punctului de date pe care o reprezintă.

d3.select(this.refs.temperatures)
    .selectAll("h2")
    .data(temperatureData)
    .enter()
        .append("h2")
        .text((datapoint) => datapoint + " degrees")

Putem utiliza o funcție săgeată pentru a lua valoarea punctului de date și pentru a restabili valoarea adăugată la „grade”. Funcțiile din proprietăți ne permit să devenim creativi cu elementele. În acest exemplu din Documentația D3, unui paragraf i se dă o culoare aleatorie folosind o funcție pentru a seta proprietatea stilului elementelor.

d3.selectAll("p")
    .style("color", function() {
        return "hsl(" + Math.random() * 360 + ",100%,50%)";
    }
);

Puteți utiliza, de asemenea, condiționali, la fel ca în orice funcție. Să presupunem că vrem să setăm stilul unui element din lista noastră de temperatură pe baza datelor.

d3.select(this.refs.temperatures)
    .selectAll("h2")
    .data(temperatureData)
    .enter()
        .append("h2")
        .text((datapoint) => `${datapoint} degrees`)
        .style((datapoint) => {
            if (datapoint > 10) {
                return "red"
            } else { return "blue" }     
        }) 

Cu toate acestea, adăugarea de stiluri în linie este o sarcină plictisitoare și am dori să folosim în schimb clase și id-uri, astfel încât să putem seta stilurile în CSS-ul nostru. Pentru a seta atribute precum clase și id-uri, le folosim .attr(). Codul de mai sus ar putea fi refactorizat .attr("class", (datapoint) => { datapoint > 10 ? "highTemperature" : "lowTemperature" }.

Animare cu tranziții

În cele din urmă, D3 facilitează tranzițiile de animare. Am putea schimba culoarea textului în roșu.

d3.select(this.ref.descr)
    .transition()
    .style("background-color", "red");
render(<p ref="descr"></p>)

Putem modifica animația pentru a se produce după 1 secundă folosind .duration(1000). De asemenea, putem folosi funcții împreună cu tranziții. De exemplu, putem face ca elementele noastre să apară într-o tranziție eșalonată. Următorul exemplu din documentația D3 face ca cercurile să apară pe rând, folosind un delay() funcție care ia dataPoint și iteration ca parametri și returnează iterația înmulțită cu 10. Iterarea se referă la poziția punctului de date în lista de date.

d3.selectAll("circle").transition()
    .duration(750)
    .delay(function(dataPoint, iteration) => iteration * 10)
    .attr("r", (dataPoint) => Math.sqrt(d * scale))

Prima noastră diagramă

Să creăm o componentă nouă. Creați un fișier nou, numit BarChart.js. Modificați App.js pentru a arăta astfel.

import React from React
import BarChart from './BarChart'
const App = () => {
    return ( <BarChart /> )
}

Lipiți următoarea placă de cazan în BarChart.js. Apel npm start pentru a porni aplicația.

import React, { Component } from 'react'
import * as d3 from 'd3'
class BarChart extends Component {
    componentDidMount() {
        const data = [ 2, 4, 2, 6, 8 ]
        this.drawBarChart(data)
    }
    drawBarChart(data)  {}
    render() { return <div ref="canvas"></div> }
}
export default BarChart

Avem un set de date fictive, pe care le transferăm funcției de desen ca parametru. De acum înainte vom lucra în interior drawBarChart(). Mai întâi, selectați div cu referința canvas. Interior drawBarChart(), anexăm un svg element din interiorul div ne-am referit. Am setat svg să aibă un cu 600, o înălțime de 400 și un chenar negru. Ar trebui să vedeți această casetă goală apărând pe pagină.

const svgCanvas = d3.select(this.refs.canvas)
    .append(“svg”)
    .attr(“width”, 600)
    .attr(“height”, 400)
    .style(“border”, “1px solid black”)
Cum sa incepeti cu D3 si React
Un element SVG gol cu ​​o margine neagră.

În continuare, avem nevoie de câteva bare pe diagrama noastră de bare. Selectăm toate rect elemente sau dreptunghiuri ale svg. Apoi adăugăm datele la dreptunghiuri și folosim Enter pentru a intra în date. Pentru fiecare dată din element, adăugăm un dreptunghi cu lățimea de 40 și înălțimea valorii punctului de date înmulțit cu 20.

svgCanvas.selectAll(“rect”)
    .data(data).enter()
         .append(“rect”)
         .attr(“width”, 40)
         .attr(“height”, (datapoint) => datapoint * 20)
         .attr(“fill”, “orange”)
1611594306 880 Cum sa incepeti cu D3 si React
După adăugarea dreptunghiurilor cu date în SVG.

Stai, de ce se pare că avem doar un dreptunghi? Deoarece nu am specificat unde pe svg dreptunghiul ar trebui să apară, toate s-au îngrămădit la 0, 0. Să le adăugăm pozițiile x și y. Să refacturăm și codul pentru a păstra lățimea, înălțimea și scala barelor în variabile.

drawBarChart(data) {
const canvasHeight = 400
const canvasWidth = 600
const scale = 20
const svgCanvas = d3.select(this.refs.canvas)
    .append(“svg”)
    .attr(“width”, canvasWidth)
    .attr(“height”, canvasHeight)
    .style(“border”, “1px solid black”)
svgCanvas.selectAll(“rect”)
    .data(data).enter()
        .append(“rect”)
        .attr(“width”, 40)
        .attr(“height”, (datapoint) => datapoint * scale)
        .attr(“fill”, “orange”)
        .attr(“x”, (datapoint, iteration) => iteration * 45)
        .attr(“y”, (datapoint) => canvasHeight — datapoint * scale)
}

Acum setăm poziția x la iterația înmulțită cu 45, care este cu 5 mai lată decât lățimea coloanei, lăsând un mic spațiu între coloane. Poziția y este puțin mai complicată. L-am setat la înălțimea pânzei minus înălțimea barei, care este valoarea punctului de date înmulțită cu 20. Acum, graficul nostru arată astfel.

1611594306 49 Cum sa incepeti cu D3 si React
După setarea pozițiilor x și y ale dreptunghiurilor.

Pentru a da barelor noastre o notă finală, să adăugăm valorile punctelor de date la bare. Adăugăm câteva elemente text la svg și setați atributul x cu 10 unități mai mare decât fiecare punct de pornire al barelor. Setăm atributul y să fie cu 10 unități mai mic decât punctul de pornire al barei.

svgCanvas.selectAll(“text”)
    .data(data).enter()
        .append(“text”)
        .attr(“x”, (dataPoint, i) => i * 45 + 10)
        .attr(“y”, (dataPoint, i) => canvasHeight - dataPoint * scale - 10)
        .text(dataPoint => dataPoint)
1611594307 438 Cum sa incepeti cu D3 si React
Adăugarea etichetelor text în barele noastre.

Acum textele stau chiar deasupra barelor. Puteți continua să lucrați cu graficul, adăugând stiluri (folosind .attr("class", "bar") ) și adăugarea unui fișier CSS. De asemenea, puteți adăuga o axă în diagramă și puteți adăuga un sfat de instrumente atunci când treceți cu mouse-ul peste bară.

Fii creativ și bucură-te!

Lucrul cu D3 poate părea dificil la început. Odată ce obțineți elementele de bază, acesta devine un instrument puternic de exprimare și vizualizare a datelor. Vă recomand să utilizați D3 pentru a alege o bibliotecă de diagrame gata făcute, deoarece permite piese mai personale și modificabile.

În cele din urmă, învățarea D3 este, de asemenea, o modalitate bună de a deveni fluent la traversarea și manipularea DOM. Înțelegerea DOM este adesea un intervievator de calitate pe care îl caută dezvoltatorii front-end.

Resurse:

D3 Tutoriale sugerat de D3

Tutorial React din documentația React