2017-07-18 4 views
0

Ich möchte mein Balkendiagramm aktualisieren, wenn ich einen Wert per Optionsfeld auswählen. Dieser Wert wird als Parameter meiner Abfrage übergeben, um entsprechende JSON-Daten zu erhalten.Wie D3 Balkendiagramm neu zu zeichnen

Der Code funktioniert gut, einen Aspekt ausgenommen. Wenn ich einen Wert durch Klicken auf ein Optionsfeld auswähle, wird das Balkendiagramm über das vorhandene Balkendiagramm gezeichnet. Ich möchte, dass das Diagramm jedes Mal neu gezeichnet wird, wenn ich eine neue Option auswähle.

// set the dimensions of the canvas 
var margin = {top: 20, right: 20, bottom: 70, left: 40}, 
    width = 600 - margin.left - margin.right, 
    height = 300 - margin.top - margin.bottom; 

// set the ranges 
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05); 

var y = d3.scale.linear().range([height, 0]); 

// define the axis 
var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 

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

var compSvg = d3.select(".company"); 

var companies = []; 
d3.json("http://localhost:8983/solr/techproducts/select?q=popularity:[10%20TO%20*]&wt=json&fl=cat&facet=true&facet.field=cat", function(error, resp) { 

    var results = resp.facet_counts.facet_fields.cat; 
    for (var i = 0; i < 5; i++) { 
     var value = results[i*2]; 
     companies.push(value); 
    } 
}); 


//functions for toggling between data 
function change(value){ 
    update(value); 
} 

function update(comp){ 
    var query = 'cat:"' + comp + '"'; 

    var url = "http://localhost:8983/solr/techproducts/select?q=" + encodeURIComponent(query) + "&rows=10&fl=manu,price&wt=json" 


    // load the data 
    d3.json(url, function(error, resp) { 

      if (error) return console.error(error); 

      resp.response.docs.forEach(function(d) { 
       d.manu = d.manu; 
       d.price = +d.price; 
      }); 

      // scale the range of the data 
      x.domain(resp.response.docs.map(function(d) { return d.manu; })); 
      y.domain([0, d3.max(resp.response.docs, function(d) { return d.price; })]); 

      // add axis 
      compSvg.append("g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + height + ")") 
       .call(xAxis) 
      .selectAll("text") 
       .style("text-anchor", "end") 
       .attr("dx", "-.8em") 
       .attr("dy", "-.55em") 
       .attr("transform", "rotate(-90)"); 

      compSvg.append("g") 
       .attr("class", "y axis") 
       .call(yAxis) 
      .append("text") 
       .attr("transform", "rotate(-90)") 
       .attr("y", 5) 
       .attr("dy", ".71em") 
       .style("text-anchor", "end") 
       .text("Price"); 


      // Add bar chart 
      compSvg.selectAll("bar") 
       .data(resp.response.docs) 
      .enter().append("rect") 
       .attr("class", "bar") 
       .attr("x", function(d) { return x(d.manu); }) 
       .attr("width", x.rangeBand()) 
       .attr("y", function(d) { return y(d.price); }) 
       .attr("height", function(d) { return height - y(d.price); }); 

    }); 

} 
+0

Haben Sie versucht, 'd3.selectAll ("bar") entfernen();' und es als das erste Element in dem Anruf getätigt wird.? –

+0

'compSvg.selectAll (" bar ")' wird Ihnen immer eine leere Auswahl geben, daher fügt die Eingabeauswahl nach dem Einstellen der Daten immer neue Rechtecke hinzu. Probieren Sie: 'compSvg.selectAll (". Bar ") - Sie fügen' rect' Elemente mit den Klassen 'bar', nicht' bar' Elementen hinzu. –

+0

@AndrewReid Das ist eine Verbesserung, aber es wird keinen großen Unterschied machen: OP hat nur eine "Enter" -Auswahl, keine Update- oder Exit-Auswahl. Das ist sein Problem hier. –

Antwort

2

Wenn Sie die Charts zum ersten Mal laden, funktioniert alles wie erwartet: Sie haben eine Null-Auswahl haben, und die Enter-Auswahl schafft ein Element für jedes Element im Datenarray. Sie fügen auch Achsen hinzu.

Wenn Sie die Diagramme das zweite Mal mit der change Funktion laden, wiederholen Sie, was Sie getan haben, um die Diagramme an erster Stelle zu erstellen: Sie haben eine Nullauswahl, wie selectAll("bar") wird leer sein, und die Eingabeauswahl erstellt ein neues Element für jedes Element im Datenarray. Sie fügen auch Achsen hinzu.

Sie müssen die Aktualisierung und Ausfahrt Auswahl verwenden, um richtig diese Arbeit zu machen:

Nachdem die Anfangsdaten angehängt werden Sie benötigen eine Update Auswahl verwenden, um die Stangen zu verändern, eine Eingabe in neuen Bars zu bringen (wenn ein Dataset verwendet mehr Balken als ein anderer) und eine Exit-Auswahl, um nicht benötigte Balken zu verlassen (wenn ein Datensatz weniger Balken als ein anderer verwendet). Es gibt eine Menge Informationen online auf der Eingabe, Aktualisierung, Exit-Prozess; Beachten Sie, dass es Unterschiede zwischen v4 und v3 gibt.

Das sieht aus wie:

var data = [ 
 
    [1,2,3,4,5], 
 
    [6,4,3], 
 
    [5,10,1,7,1,3] 
 
]; 
 

 
var i = 0; 
 

 
var width = 500; 
 
var height = 500; 
 

 
var svg = d3.select("body") 
 
    .append("svg") 
 
    .attr("width",width) 
 
    .attr("height",height); 
 
    
 
var y = d3.scale.linear().range([height, 0]); 
 
var x = d3.scale.ordinal().rangeRoundBands([0, width], .05); 
 

 

 
update(data[0]); 
 
timer(); 
 

 
function update(dataset) { 
 

 
    // update scales 
 
    y.domain([0,d3.max(dataset, function(d) { return d; })]); 
 
    x.domain(dataset.map(function(d,i) { return i; })); 
 
    
 
    // Bind Data 
 
    var bars = svg.selectAll(".bars") 
 
    .data(dataset); 
 
    
 
    // Update existing bars: 
 
    bars.transition() 
 
    .attr("x",function(d,i) { return x(i); }) 
 
    .attr("y",function(d) { return y(d); }) 
 
    .attr("width", x.rangeBand()) 
 
    .attr("height", function(d) { return height - y(d); }) 
 
    .duration(1000); 
 
    
 
    
 
    // New Bars 
 
    bars.enter() 
 
    .append("rect") 
 
    .attr("class","bars") 
 
    .attr("x",function(d,i) { return x(i); }) 
 
    .attr("width", x.rangeBand()) 
 
    .attr("y",height) 
 
    .attr("height",0) 
 
    .transition() 
 
    .attr("y",function(d) { return y(d); }) 
 
    .attr("height", function(d) { return height - y(d); }) 
 
    .duration(1000);; 
 
    
 
    // Un-needed Bars: 
 
    bars.exit() 
 
    .transition() 
 
    .attr("height", 0) 
 
    .duration(1000) 
 
    .remove(); 
 
    
 
} 
 

 
function timer() { 
 
    setTimeout(function() { update(data[i++%3]); timer() } , 1500); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

+0

+ eins für die Verknüpfung von S.O. Dokumente Leider sind die Docs sowieso tot ... –

-1

Eine kleine Änderung kann Ihre Notwendigkeit erfüllen:

function change(value){ 
    // erase all contents before update 
    compSvg.html(""); 
    update(value); 
}