2013-02-08 10 views
6

Ci sono stato per un paio di settimane e non riesco a capire come disegnare il grafico sottostante con percorsi multipli. Focus+Context via Brushing chartProblemi a disegnare d3.js Focus + Contesto via Grafico a pennello con più percorsi

Ho provato a creare un jsfiddle ma non sono riuscito a replicare lo schermo che ottengo. A questo punto, quello che ho è simile al grafico originale, solo con un percorso invece di un'area e il lavoro di spazzolamento funziona. Fondamentalmente cercando di combinare il grafico di messa a fuoco e il grafico a linee multi-serie Multiseries chart.

Tuttavia, quando provo ad aggiungere un altro percorso, niente funziona. Si prega di suggerire eventuali idee o modifiche che devo apportare affinché funzioni. Ci sono anche altri grafici simili (o grafici) che posso guardare. I dati potrebbero essere riorganizzati in qualsiasi modo o forma affinché funzioni.

Jsfiddle

<div id='dashboardChart'> 
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
id="svg"> 
</div> 

path { 
fill:none; 
stroke:white; 
stroke-width:2px; 
} 
.axis path, .axis line { 
    fill: none; 
    stroke: #CCC; 
    shape-rendering: crispEdges; 
} 
.brush .extent { 
    stroke: #fff; 
    fill-opacity: .125; 
    shape-rendering: crispEdges; 
} 
.path_green { 
    stroke:green; 
} 
.path_red { 
    stroke:red; 
} 
.path_yellow { 
    stroke:yellow; 
} 

function drawChart() { 
    var margin = { 
     top: 5, 
     right: 10, 
     bottom: 100, 
     left: 50 
    }, 
    margin2 = { 
     top: 200, 
     right: 10, 
     bottom: 20, 
     left: 50 
    }, 
    width = 1075 - margin.left - margin.right, 
     height = 280 - margin.top - margin.bottom, 
     height2 = 280 - margin2.top - margin2.bottom; 

    var parseDate = d3.time.format("%Y-%m-%d").parse; 

    var x = d3.time.scale().range([0, width]), 
     x2 = d3.time.scale().range([0, width]), 
     y = d3.scale.linear().range([height, 0]), 
     y2 = d3.scale.linear().range([height2, 0]); 

    var xAxis = d3.svg.axis().scale(x).orient("bottom"), 
     xAxis2 = d3.svg.axis().scale(x2).orient("bottom"), 
     yAxis = d3.svg.axis().scale(y).orient("left"); 

    var brush = d3.svg.brush() 
     .x(x2) 
     .on("brush", brush); 

    var area = d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
     return x(d.date); 
    }) 
     .y0(height) 
     .y1(function (d) { 
     return y(d.red); 
    }); 

    var area2 = d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
     return x2(d.date); 
    }) 
     .y0(height2) 
     .y1(function (d) { 
     return y2(d.red); 
    }); 

    var svg = d3.select("#dashboardChart #svg") 
     .attr("width", width + margin.left + margin.right) 
     .attr("height", height + margin.top + margin.bottom); 

    svg.append("defs").append("clipPath") 
     .attr("id", "clip") 
     .append("rect") 
     .attr("width", width) 
     .attr("height", height); 

    var focus = svg.append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var context = svg.append("g") 
     .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); 

    var data = [{ 
     "date": "2013-02-08T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 1 
    }, { 
     "date": "2013-02-07T05:00:00.000Z", 
     "data": null, 
     "red": 485, 
     "yellow": 0, 
     "green": 491 
    }, { 
     "date": "2013-02-06T05:00:00.000Z", 
     "data": null, 
     "red": 2884, 
     "yellow": 0, 
     "green": 2881 
    }, { 
     "date": "2013-02-05T05:00:00.000Z", 
     "data": null, 
     "red": 3191, 
     "yellow": 0, 
     "green": 3188 
    }, { 
     "date": "2013-02-04T05:00:00.000Z", 
     "data": null, 
     "red": 180, 
     "yellow": 0, 
     "green": 184 
    }, { 
     "date": "2013-02-03T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-02-02T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-02-01T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-31T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-30T05:00:00.000Z", 
     "data": null, 
     "red": 1, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-29T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 2 
    }, { 
     "date": "2013-01-28T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-27T05:00:00.000Z", 
     "data": null, 
     "red": 1, 
     "yellow": 1, 
     "green": 1 
    }, { 
     "date": "2013-01-26T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 1 
    }, { 
     "date": "2013-01-25T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-24T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-23T05:00:00.000Z", 
     "data": null, 
     "red": 49, 
     "yellow": 0, 
     "green": 45 
    }, { 
     "date": "2013-01-22T05:00:00.000Z", 
     "data": null, 
     "red": 59, 
     "yellow": 0, 
     "green": 64 
    }, { 
     "date": "2013-01-21T05:00:00.000Z", 
     "data": null, 
     "red": 119, 
     "yellow": 1, 
     "green": 125 
    }, { 
     "date": "2013-01-20T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 1, 
     "green": 0 
    }, { 
     "date": "2013-01-19T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-18T05:00:00.000Z", 
     "data": null, 
     "red": 84, 
     "yellow": 0, 
     "green": 81 
    }, { 
     "date": "2013-01-17T05:00:00.000Z", 
     "data": null, 
     "red": 76, 
     "yellow": 1, 
     "green": 77 
    }, { 
     "date": "2013-01-16T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 1, 
     "green": 0 
    }, { 
     "date": "2013-01-15T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-14T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-13T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-12T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-11T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }, { 
     "date": "2013-01-10T05:00:00.000Z", 
     "data": null, 
     "red": 0, 
     "yellow": 0, 
     "green": 0 
    }]; 

    x.domain(d3.extent(data.map(function (d) { 
     return d.date; 
    }))); 
    y.domain([0, d3.max(data.map(function (d) { 
     return d.red; 
    }))]); 
    x2.domain(x.domain()); 
    y2.domain(y.domain()); 

    focus.append("path") 
     .datum(data) 
     .attr("clip-path", "url(#clip)") 
     .attr("d", area) 
     .attr("class", "path_red"); 

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

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

    context.append("path") 
     .datum(data) 
     .attr("d", area2) 
     .attr("class", "path_red"); 

    context.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height2 + ")") 
     .call(xAxis2); 

    context.append("g") 
     .attr("class", "x brush") 
     .call(brush) 
     .selectAll("rect") 
     .attr("y", -6) 
     .attr("height", height2 + 7); 

    function brush() { 
     x.domain(brush.empty() ? x2.domain() : brush.extent()); 
     focus.select("path").attr("d", area); 
     focus.select(".x.axis").call(xAxis); 
    } 
} 
drawChart(); 
+0

sono stato in grado di disegnare 3 aree di replicare 3 set di dati uno sopra l'altro ma non in grado di "spazzolare" tutti e tre. Funziona solo con un'area. È possibile "spazzolare" il lavoro su tre aree contemporaneamente? Come può essere codificato? –

risposta

10

Secondo il vostro commento è stati in grado di tracciare i tre settori, ma aveva difficoltà a spazzolatura loro. Ho un esempio di lavoro qui: http://jsfiddle.net/BVzyq/1/ in cui, ho aggiunto tre elementi <path> corrispondenti ai tre colori nei dati: ['red', 'yellow', 'green'].

ho Sottratto le funzioni che potrebbe assumere in un colore e di ritorno il valore appropriato d:

var area = function (color) { 
    return d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
      return x(d.date); 
     }) 
     .y0(height) 
     .y1(function (d) { 
      return y(d[color]); 
     }); 
}; 

var area2 = function (color) { 
    return d3.svg.area() 
     .interpolate("monotone") 
     .x(function (d) { 
      return x2(d.date); 
     }) 
     .y0(height2) 
     .y1(function (d) { 
      return y2(d[color]); 
     }); 
}; 

Possono essere astratte ulteriormente, ma questi sono i più vicini al codice che hai scritto. Queste funzioni vengono utilizzate durante la creazione dei percorsi:

focus.selectAll('path') 
    .data(['red', 'yellow', 'green']) 
    .enter() 
    .append('path') 
    .attr('clip-path', 'url(#clip)') 
    .attr('d', function (col) { 
     return area(col)(data); 
    }) 
    .attr('class', function (col) { 
     return "path_" + col + " data"; 
    }); 

// ... 

context.selectAll('path') 
    .data(['red', 'yellow', 'green']) 
    .enter() 
    .append('path') 
    .attr('d', function (col) { 
     return area2(col)(data); 
    }) 
    .attr('class', function (col) { 
     return "path_" + col; 
    }); 

Le classi CSS sembravano suggerire questa forma di dati si uniscono. Ho anche aggiunto un'altra classe data ai percorsi che corrispondono ai grafici delle serie temporali. Ciò semplifica la distinzione di questi <path> da quelli destinati all'asse.

Infine, nella funzione pennello, ricalcolare l'attributo d per tutti path.data elementi:

function brush() { 
    x.domain(brush.empty() ? x2.domain() : brush.extent()); 
    focus.selectAll("path.data").attr("d", function (col) { 
     return area(col)(data); 
    }); 
    focus.select(".x.axis").call(xAxis); 
} 

nota che ho cambiato alcuni dei valori in data per rendere tutti i tre colori visibile.

+2

Fantastico, ti meriti una medaglia. – Melki

2

Ottima soluzione musically_ut, per gli altri che hanno un problema simile. Sono stato in grado di caricare csv aggiuntivi, come nell'esempio trovato in questo link - Focus+Context via Brushing ma sono stato davvero bloccato su come spazzolare tutte le linee insieme, anche se entrambi erano correttamente visualizzati in area e area2.

Risulta, guardando il tuo codice, tutto quello che dovevo fare era cambiare focus.select per mettere a fuoco.seleziona Tutto quello che hai. Grazie!

E per tutti coloro che lavorano con il codice tutorial originale, è possibile aggiungere csv alternativo è solo copiando il seguente codice e indicando il vostro nuovo csv:

d3.csv("sp501.csv", function(error, data) { 

     data.forEach(function(d) { 
     d.date = parseDate(d.date); 
     d.price = +d.price; 
     }); 

     x.domain(d3.extent(data.map(function(d) { return d.date; }))); 
     y.domain([0, d3.max(data.map(function(d) { return d.price; }))]); 
     x2.domain(x.domain()); 
     y2.domain(y.domain()); 

     focus.append("path") 
      .datum(data) 
      .attr("clip-path", "url(#clip)") 
      .attr("d", area) 
      .attr("class", "timeLine2"); 

     context.append("path") 
      .datum(data) 
      .attr("class", "timeLine2") 
      .attr("d", area2); 

     context.append("g") 
      .attr("class", "x axis2") 
      .attr("transform", "translate(0," + height2 + ")") 
      .call(xAxis2); 

     context.append("g") 
      .attr("class", "x brush") 
      .call(brush) 
     .selectAll("rect") 
      .attr("y", -6) 
      .attr("height", height2 + 7); 
    }); 
Problemi correlati