2017-07-18 147 views
0

我想通过单选按钮选择一个值时更新我的​​条形图。此值作为我的查询的参数传递以获取相应的JSON数据。如何重新绘制D3条形图

该代码工作正常,排除一个方面。当我通过单击任何单选按钮来选择一个值时,条形图将绘制在现有条形图的顶部。我希望每次选择新选项时都要重新绘制图表。

// 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

您是否尝试过'd3.selectAll( “酒吧”),删除();'并把它作为调用的第一个项目。? –

+0

'compSvg.selectAll(“bar”)'总是会给你一个空的选择,因此在设置数据后,输入选择将总是追加新的矩形。尝试:'compSvg.selectAll(“.bar”) - 您正在将'rect'元素附加到'bar'类,而不是'bar'元素。 –

+0

@AndrewReid这是一个改进,但它没有什么区别:OP只有一个“输入”选择,没有更新或退出选择。这是他/她的问题。 –

回答

2

当加载排行榜的第一次,一切正常:你有一个空的选择和输入选择创建了一个元素用于数据数组中的每个项目。您还附加轴。

当您第二次使用change函数加载图表时,您首先重复做了哪些操作来创建图表:由于selectAll("bar")将为空,并且输入选项会创建一个新选项元素用于数据数组中的每个项目。您还附加轴。

您需要使用更新并退出选择正确,使这项工作:

初始数据追加后,您需要使用更新的选择修改酒吧,一个进入新的酒吧带来的(如果一个数据集比另一个数据集使用更多条)和退出选择以退出不需要的条(如果一个数据集使用的条比其他条更少)。网上有很多关于进入,更新,退出流程的信息;请记住,v4和v3之间存在差异。

这看起来像:

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

+一个用于链接S.O.文档。不幸的是,Docs已经死了...... –

-1

稍加修改可以满足你的需要:

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