2016-05-17 14 views
3

Ich bin ziemlich neu zu D3 und Codierung im Allgemeinen. Ich versuche, ein Balkendiagramm einzurichten, das Daten abhängig von einem Kontrollkästchen enthält/ausschließt. Ich habe eine Reihe von Produktgruppen und Ländern, die ich in die durch die Leiste dargestellte Gesamtsumme ein- und ausschalten möchte. Die Ausgabe sollte einen Balken pro Produkt betragen.Dynamische Filterung mit D3

Mein vollständiger Datensatz enthält viele weitere Produkte, Produktgruppen und Länder. Daher ist es nicht sinnvoll, ein Schlüssel/Wert-Paar für jede mögliche Kombination von Kontrollkästchen zu erstellen. Stattdessen möchte ich eine Funktion erstellen, die die Kontrollkästchen neu bewertet und die Daten neu filtert und das Rollup aktualisiert, wenn ein Kontrollkästchen geändert wird.

Ich bin mir nicht sicher, wo diese Funktion in meinem Code sitzen sollte oder was sollte es wie ... Dieser Blick ist, was mit arbeite ich im Moment:

var data = data.filter(function(d) { 
    if (document.getElementById("nz_button").checked) { 
     return d.country == 'NZ' 
    } 
    if (document.getElementById("au_button").checked) { 
     return d.country == 'AU' 
    } 
    if (document.getElementById("us_button").checked) { 
     return d.country == 'US' 
    } 
    }) 


    // to see how many distinct groups there are and sum volume 
    var products = d3.nest() 
    .key(function(d) { 
     return d.product 
    }) 
    .rollup(function(leaves) { 
     var sum = 0; 
     leaves.forEach(function(d) { 
     sum += d.volume; 
     }) 
     return sum 
    }) 
    .entries(data); 

Voll Code: http://plnkr.co/edit/qezdwMLt48RPc8KH17hS?p=preview

Vielleicht sollte ich mit Auswahlen arbeiten und das Nest/Rollup bei Bedarf erneut ausführen?

Jede Hilfe wird geschätzt. Thanks :)

Antwort

2

Sie können den vollständigen Code bewegen, die die Grafik in einer neuen Funktion wie diese macht:

function makeDataGraph(data) {//function to make the graph. 
     // 
     // FILTER 
     // 
     var data = data.filter(function(d) { 
     if (document.getElementById("au_button").checked) { 
      return d.country == 'AU' 
     } 
     if (document.getElementById("us_button").checked) { 
      return d.country == 'US' 
     } 
     if (document.getElementById("nz_button").checked) { 
      return d.country == 'NZ' 
     } 

     }) 


     // to see how many distinct groups there are and sum volume 
     var products = d3.nest() 
     .key(function(d) { 
      return d.product 
     }) 
     .rollup(function(leaves) { 
      var sum = 0; 
      leaves.forEach(function(d) { 
      sum += d.volume; 
      }) 
      return sum 
     }) 
     .entries(data); 

     // sorting on descending total 
     console.log(products); 
     products.sort(function(a, b) { 
     return b.values - a.values 
     }) 

     var max = d3.max(products, function(d) { 
     return d.values; 
     }); 
     var xscale = d3.scale.linear() 
     .domain([0, max]) 
     .range([0, 600]) 

     var svg = d3.select("svg"); 



     // 
     // Still needs to be cleaned up \/ \/ 
     // 

     var rects = svg.selectAll("rect.product") 
     .data(products) 
     rects.exit().remove(); 
     rects.enter().append("rect").classed("product", true) 
     rects.attr({ 
     x: 200, 
     y: function(d, i) { 
      return 100 + i * 50 
     }, 
     width: function(d, i) { 
      return xscale(d.values) 
     }, 
     height: 50 
     }).on("click", function(d, i) { 
     console.log(i, d); 
     }) 


     var labels = svg.selectAll("text.label") 
     .data(products) 
     labels.exit().remove(); 
     labels.enter().append("text").classed("label", true) 
     labels.attr({ 
     x: 195, 
     y: function(d, i) { 
      return 128 + i * 50 
     }, 
     "text-anchor": "end", 
     "alignment-baseline": "middle" 
     }).text(function(d) { 
     return d.key || "N/A" 
     }) 


     var volume = svg.selectAll("text.volume") 
     .data(products); 
     volume.exit().remove(); 
     volume.enter().append("text").classed("volume", true) 
     volume.attr({ 
     x: function(d, i) { 
      return 205 + xscale(d.values) 
     }, 
     y: function(d, i) { 
      return 128 + i * 50 
     }, 
     "text-anchor": "start", 
     "alignment-baseline": "middle" 
     }).text(function(d) { 
     return d.values || "N/A" 
     }) 
    } 

Denken Sie daran, rects.exit().remove(); so zu tun, dass, wenn die Daten auf Klick auf die Checkbox geändert wird, Rechtecke verwandten zu alten Daten wird entfernt.

Jetzt können Sie diese Funktion aus dem Click-Ereignis aufrufen und auch die tsv wie diese Afterloading:

d3.tsv("data.tsv", function(err, udata) { 

    var udata = udata.map(process); 
    console.log("udata", udata); 

    var data = udata // making new var to preserve unfiltered data 
    makeDataGraph(data);//call the function to make graph 

    function handleClick() { // event handler... 
    makeDataGraph(data) 
    } 
    //add listener to all check boxes. 
    d3.selectAll(".filter_button").on("click", handleClick); 
}); 

Arbeits Code here

+1

Thank you! Das bringt mich größtenteils dorthin, um die if-Anweisungen im Filter herauszufinden ... – alexalex