2011-12-31 15 views
38

Fino ad ora, ho utilizzato i loop per aggiungere elementi di linea a una visualizzazione D3, ma questo non sembra nello spirito dell'API.Disegno di più righe in D3.js

Diciamo che ho avuto alcuni dati,

var data = {time: 1, value: 2, value2: 5, value3: 3,value4: 2}, 
      {time: 2, value: 4, value2: 9, value3: 2,value4: 4}, 
      {time: 3, value: 8, value2:12, value3: 2,value4:15}]); 

mi piacerebbe quattro linee, con il tempo, come la X per tutti 4.

posso fare qualcosa di simile:

E quindi aggiungere questi uno per uno (o da un ciclo).

var line1 = group.selectAll("path.path1") 
     .attr("d",l(data)); 
var line2 = group.selectAll("path.path2") 
     .attr("d",l2(data)); 
var line3 = group.selectAll("path.path3") 
     .attr("d",l3(data)); 
var line4 = group.selectAll("path.path4") 
     .attr("d",l4(data)); 

C'è un modo migliore più generale di aggiunta di questi percorsi?

risposta

72

Sì. In primo luogo vorrei ristrutturare i propri dati per una più facile iterazione, in questo modo:

var series = [ 
    [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 8}], 
    [{time: 1, value: 5}, {time: 2, value: 9}, {time: 3, value: 12}], 
    [{time: 1, value: 3}, {time: 2, value: 2}, {time: 3, value: 2}], 
    [{time: 1, value: 2}, {time: 2, value: 4}, {time: 3, value: 15}] 
]; 

Ora è necessario solo una singola linea generica:

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

E, è quindi possibile aggiungere tutti gli elementi di percorso in un colpo solo :

group.selectAll(".line") 
    .data(series) 
    .enter().append("path") 
    .attr("class", "line") 
    .attr("d", line); 

Se si vuole fare il formato di struttura dei dati più piccolo, si potrebbe anche estrarre i tempi in un array separato, e quindi utilizzare una matrice 2D per i valori. Che sarebbe simile a questa:

var times = [1, 2, 3]; 

var values = [ 
    [2, 4, 8], 
    [5, 9, 12], 
    [3, 2, 2], 
    [2, 4, 15] 
]; 

Dato che la matrice non include il valore del tempo, è necessario guardare in su dalla x-di accesso del generatore di linea. D'altra parte, il y-di accesso è semplificato in quanto è possibile passare il valore della matrice direttamente al y-scala:

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

Creazione degli elementi rimane la stessa:

group.selectAll(".line") 
    .data(values) 
    .enter().append("path") 
    .attr("class", "line") 
    .attr("d", line); 
+1

Mike, ho usato il tuo esempio qui per fare alcuni progressi su più linee, ma come transizioni? Chiedendosi se si potrebbe eyeball questa domanda per favore: http://stackoverflow.com/questions/10404283/d3-js-transform-transition-multiple-lines - Grazie! – August

+0

x (d.time); sembra essere errato - non c'è una funzione particolare per questo; funziona solo se lo si cambia in semplicemente d.time. Lo stesso per il y corrispondente. – LittleBobbyTables

+14

'x' e' y' si riferiscono a scale, che è necessario definire prima di utilizzare. – mbostock