2014-09-17 18 views
11

Quindi ho un grafico che traccia il traffico rispetto alla data e alla tariffa rispetto alla data. Sto cercando di sfumare l'area tra le due linee. Tuttavia, voglio ombreggiare un colore diverso a seconda di quale linea è più alta. Le seguenti opere senza che lo scorso requisito:Utilizzo di d3 nell'area di ombreggiamento tra due linee

var area = d3.svg.area() 
    .x0(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .x1(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .y0(function(d) { return y(parseInt(d.original.traffic)); }) 
    .y1(function(d) { return y(parseInt(d.original.rate)); }) 

Tuttavia, aggiungendo che lo scorso requisito, ho cercato di usare definiti():

.defined(function(d){ return parseInt(d.original.traffic) >= parseInt(d.original.rate); }) 

Ora questo funziona per lo più, a meno che le linee si incrociano. Come oscuro l'area sotto una linea TRA punti? È un'ombreggiatura basata sui punti e voglio che si oscuri in base alla linea. Se non ho due punti consecutivi su un lato della linea, non ottengo alcuna ombreggiatura.

risposta

13

Poiché non si dispone di punti dati negli incroci, la soluzione più semplice è probabilmente quella di ottenere le aree sopra e sotto ogni riga e utilizzare clipPath s per ritagliare la differenza.

Suppongo che tu stia usando d3.svg.line per disegnare le linee su cui sono basate le aree. In questo modo saremo in grado di ri-utilizzare le funzioni .x() e .y() accessor sulle aree successive:

var trafficLine = d3.svg.line() 
    .x(function(d) { return x(d3.time.format("%m/%d/%Y").parse(d.original.date)); }) 
    .y(function(d) { return y(parseInt(d.original.traffic)); }); 

var rateLine = d3.svg.line() 
    .x(trafficLine.x()) // reuse the traffic line's x 
    .y(function(d) { return y(parseInt(d.original.rate)); }) 

È possibile creare funzioni un'area separata per il calcolo delle aree sia sopra che sotto le due linee. L'area sotto ogni linea verrà utilizzata per tracciare il percorso effettivo e l'area sopra verrà utilizzata come tracciato di ritaglio. Ora possiamo riutilizzare le funzioni di accesso dalle linee:

var areaAboveTrafficLine = d3.svg.area() 
    .x(trafficLine.x()) 
    .y0(trafficLine.y()) 
    .y1(0); 
var areaBelowTrafficLine = d3.svg.area() 
    .x(trafficLine.x()) 
    .y0(trafficLine.y()) 
    .y1(height); 
var areaAboveRateLine = d3.svg.area() 
    .x(rateLine.x()) 
    .y0(rateLine.y()) 
    .y1(0); 
var areaBelowRateLine = d3.svg.area() 
    .x(rateLine.x()) 
    .y0(rateLine.y()) 
    .y1(height); 

... dove height è l'altezza del grafico, e supponendo 0 è la coordinata y della parte superiore del grafico, altrimenti modificare tali valori di conseguenza.

Ora è possibile utilizzare le funzioni per superficie di cui sopra per creare tracciati di ritaglio in questo modo: sono necessari

var defs = svg.append('defs'); 

defs.append('clipPath') 
    .attr('id', 'clip-traffic') 
    .append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaAboveTrafficLine); 

defs.append('clipPath') 
    .attr('id', 'clip-rate') 
    .append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaAboveRateLine); 

I id attributi perché abbiamo bisogno di fare riferimento a queste definizioni, quando in realtà i percorsi di ritaglio.

Infine, utilizzare le funzioni dell'area inferiore per tracciare percorsi verso lo svg. La cosa importante da ricordare è che per ogni area-sotto, abbiamo bisogno di agganciare al opposta zona-sopra, quindi l'area Tasso sarà ritagliato sulla base di #clip-traffic e viceversa:

// TRAFFIC IS ABOVE RATE 
svg.append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaBelowTrafficLine) 
    .attr('clip-path', 'url(#clip-rate)') 

// RATE IS ABOVE TRAFFIC 
svg.append('path') 
    .datum(YOUR_DATASET) 
    .attr('d', areaBelowRateLine) 
    .attr('clip-path', 'url(#clip-traffic)') 

Dopo di che dovrai solo assegnare alle due regioni diversi colori di riempimento o qualsiasi altra cosa tu voglia fare per distinguerli l'uno dall'altro. Spero possa aiutare!