2012-10-16 9 views
21

Sono un principiante di D3.js e sto imparando a giocare con i dati.D3.js che lega un oggetto ai dati e aggiunge per ogni chiave

Diciamo che avere un oggetto con nome dei tasti, e ogni tasto ha una serie di numeri in questo modo:

var userdata = { 
    'John' : [0, 1, 3, 9, 8, 7], 
    'Harry': [0, 10, 7, 1, 1, 11], 
    'Steve': [3, 1, 4, 4, 4, 17], 
    'Adam' : [4, 77, 2, 13, 11, 13] 
}; 

Per ogni utente, vorrei aggiungere un oggetto SVG e poi tracciare la linea con l'array di valori per quell'utente.

Quindi, ecco la mia ipotesi su come sarebbe basata sui tutorial, ma so che non è corretto. Questo è quello di mostrare la mia conoscenza limitata e dare una migliore comprensione di ciò che sto facendo:

Per prima cosa dovrebbe creare la linea

var line = d3.svg.line().interpolate('basis'); 

poi voglio associare i dati al mio corpo e aggiungere un elemento SVG per ogni chiave:

d3.select('body') 
    .selectAll('svg') 
    .data(userdata) 
    .enter() 
    .append('svg') 
    .append(line) 
    .x(function(d, i) { return i; }) 
    .y(function(d) { return d[i]; }); 

Quindi chiudo ??

risposta

31

Ecco un altro esempio simile a quello di mbeasley: http://jsfiddle.net/2N2rt/15/ che aggiunge asse, colori e capovolge il grafico con il lato destro verso l'alto. Innanzitutto, ho massaggiato i tuoi dati solo un po '. Funziona al meglio se si dispone di una matrice di valori e ho utilizzato i tasti per rendere più semplici le proprietà name e values.

var data = [ 
    {name: 'John', values: [0,1,3,9, 8, 7]}, 
    {name: 'Harry', values: [0, 10, 7, 1, 1, 11]}, 
    {name: 'Steve', values: [3, 1, 4, 4, 4, 17]}, 
    {name: 'Adam', values: [4, 77, 2, 13, 11, 13]} 
]; 

Generalmente in d3 si imposta il grafico come questo che determina la dimensione del grafico reale ei margini circostanti.

var margin = {top: 20, right: 80, bottom: 30, left: 50}, 
    width = 640 - margin.left - margin.right, 
    height = 380 - margin.top - margin.bottom; 

Quindi è possibile creare le scale in base ai dati. Sebbene non sia necessario crearli, rendono gli elementi di posizionamento sul grafico molto più semplici convertendo i valori in punti. Lo domain è il valore minimo e massimo dei dati, mentre lo range è il valore minimo e massimo della dimensione del grafico. Notare che il range per il y axis viene invertito che inserisce (0,0) nell'angolo in basso a sinistra (solitamente 0 per l'asse y è in alto).

var x = d3.scale.linear() 
    .domain([0, d3.max(data, function(d) { return d.values.length - 1; })]) 
    .range([0, width]); 

var y = d3.scale.linear() 
    .domain([d3.min(data, function(d) { return d3.min(d.values); }), 
      d3.max(data, function(d) { return d3.max(d.values); })]) 
    .range([height, 0]); 

d3 ha un paio di caratteristiche per la creazione automatica scale di colore per voi. Basta impostarlo con i tasti che si desidera utilizzare e il numero di colori (penso che ci siano 10 e 20 opzioni di colore).

var color = d3.scale.category10() 
    .domain(d3.keys(data[0]).filter(function(key) { return key === "name"; })); 

Qui utilizziamo le nostre scale per impostare l'asse xe y. Ci sono molte opzioni diverse per gli assi. TickFormat è utile per cambiare il modo in cui appaiono le zecche, d3.format ha molte opzioni diverse in modo che raramente devi creare un formattatore personalizzato.

var xAxis = d3.svg.axis() 
    .scale(x) 
    .tickFormat(d3.format('d')) 
    .orient("bottom"); 

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

Qui creiamo una funzione riutilizzabile che sa disegnare una linea. Passeremo ogni punto dati per ogni persona nella funzione di linea in seguito. Notare che d contiene il set corrente di valori che stiamo rappresentando e i è l'indice dei valori correnti all'interno del nostro array di dati originale.

var line = d3.svg.line() 
    .interpolate("basis") 
    .x(function(d, i) { return x(i); }) 
    .y(function(d, i) { return y(d); }); 

Finalmente possiamo iniziare ad aggiungere cose al nostro grafico, prima creando e posizionando l'elemento svg principale.

var svg = d3.select("#chart").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

Quindi accodare ciascun asse.

svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 

aggiungiamo un gruppo (g) per ogni persona e associare i dati con il gruppo. Useremo questi dati quando disegneremo le linee. Forniamo un class in modo che possiamo stilare il grafico in un secondo momento, se lo vogliamo.

var people = svg.selectAll(".people") 
     .data(data) 
    .enter().append("g") 
     .attr("class", "people"); 

Quindi, infine, tracciare le linee per ogni persona.

people.append("path") 
     .attr("class", "line") 
     .attr("d", function(d) { return line(d.values); }) 
     .style("stroke", function(d) { return color(d.name); }); 

ho usato i dati per rispondere a un'altra domanda su disegnare una griglia quando si hanno valori negativi. Puoi vedere quel grafico allo http://jsfiddle.net/2y3er/2/.

+0

Questo è un esempio eccellente, prendendo la generica generazione di linee che avevo nel mio esempio un po 'oltre per creare un grafico completamente stilizzato. Bel lavoro! – mbeasley

+0

Una cosa che ho notato è che si cambia il layout del mio oggetto. Invece, hai una matrice di 4 oggetti mentre io ho un oggetto con 4 proprietà. Ho guardato un video poco dopo aver postato questa domanda (http://vimeo.com/35005701) e si parla di mettere sempre i miei dati in questo modo. Credo che dovrò ripetere come funziona la mia funzione. – frshca

+0

Inoltre, grazie mille @ Bill. Ora hai risposto a 2 delle mie domande su D3.js! Ci rivediamo presto! – frshca

11

Direi che stai andando nella giusta direzione. Ecco quello che vorrei fare (ma sapere che non c'è un solo modo per farlo):

// your user data 
var userdata = { 
    'John' : [0, 1, 3, 9, 8, 7], 
    'Harry': [0, 10, 7, 1, 1, 11], 
    'Steve': [3, 1, 4, 4, 4, 17], 
    'Adam' : [4, 77, 2, 13, 11, 13] 
}; 

// add your main SVG block 
var svg = d3.select('body') 
    .append('svg') 
    .attr('width', 400) 
    .attr('height', 200) 
    .attr('id', 'chart'); 

// add an SVG group element for each user 
var series = svg.selectAll('g.series') 
    .data(d3.keys(userdata)) 
    .enter() 
    .append('g') 
    .attr('class', 'series'); 

// create your line generator 
var line = d3.svg.line() 
    .interpolate('basis') 
    .x(function(d, i) { 
     return i*40; // *40 just to increase the chart size 
    }) 
    .y(function(d) { 
     return d*3; // *3 for the same reason 
    }); 

// add a line for each user using your SVG grouping 
var lineSVG = series.selectAll('.line') 
    .data(d3.keys(userdata)) 
    .enter() 
    .append('svg:path') 
    .attr('d', function(d) { 
     return line(userdata[d]); 
    }) 
    .attr('class','line'); 

Here's a demo del codice di cui sopra.

Inoltre, consiglio vivamente di leggere this article, poiché aiuta davvero a solidificare il modo in cui funziona d3.

+0

grazie per l'articolo, sembra che molte persone raccomandino a tutti di leggere quell'articolo. – frshca