简体   繁体   中英

D3.js updating a stacked bar chart

I basically followed this example to construct a stacked bar chart. However, I want to update the data via a dropdown menu.

My logic goes as this: I have data in a JSON array of 15 objects. I use an array in Javascript to store each of these objects and when I pick an index from the dropdown menu, I want to load the D3 visualization of the selected object.

Currently, my stacked bar chart works and I correctly update / animate the axes when I change the index but I'm having trouble getting the graph to show. For some reason, I have to press my update button twice to get the graph to show, even though the axes show upon the first click.

My code goes like this:

d3.json call

...

function update(index) {

...

var layers = svg.selectAll(".layer")

layers.selectAll("rect")
  .data(new_layers)
  .exit()
  .transition()
    .duration(300)
  .attr("y", function(d) { return -1 * y(d.y + d.y0); })
  .remove();

layers
  .transition()
    .duration(300)
  .remove()

var new_layer = svg.selectAll(".layer")
  .data(new_layers)
.enter().append("g")
  .attr("class", "layer")
  .style("fill", function(d, i) { 
    return color(i); 
  });

new_layer.selectAll("rect")
  .data(function(d) { return d; })
.enter().append("rect")
  .attr("x", function(d) { return x(d.x); })
  .attr("y", function(d) { return y(d.y + d.y0); })
  .attr("height", function(d) { return y(d.y0) - y(d.y + d.y0); })
  .attr("width", x.rangeBand() - 1)
  .on('mouseover', tip.show)
  .on('mouseout', tip.hide);

I have a feeling it's because I create the new_layer variable and maybe that isn't fully initialized the first time I call update so I need to press it again? Not entirely sure, so any guidance would be greatly appreciated.

My code structure basically follows the example linked in the first sentence but that d3 example did not have transitions.

Please follow the standard update pattern: https://bl.ocks.org/mbostock/3808218

In your case, if you just want to remove the old layers and redraw them:

svg.selectAll(".layer").remove();

var new_layer = svg.selectAll(".layer")
  .data(new_layers)
  .enter().append("g")
  .attr("class", "layer")
  .style("fill", function(d, i) { 
    return color(i); 
  });

new_layer.selectAll("rect")
  .data(function(d) { return d; })
  .enter().append("rect")
  .attr("x", function(d) { return x(d.x); })
  .attr("y", function(d) { return y(d.y + d.y0); })
  .attr("height", function(d) { return y(d.y0) - y(d.y + d.y0); })
  .attr("width", x.rangeBand() - 1)
  .on('mouseover', tip.show)
  .on('mouseout', tip.hide);

Also, transitions are executed asynchronously, so even if your later code is sequentially after the transitions, the states may not have been updated by transitions when you reach your later code.

General Update Pattern, For your reference:

function update(data) {

  // DATA JOIN
  // Join new data with old elements, if any.
  var text = svg.selectAll("text")
      .data(data);

  // UPDATE
  // Update old elements as needed.
  text.attr("class", "update");

  // ENTER
  // Create new elements as needed.
  text.enter().append("text")
      .attr("class", "enter")
      .attr("x", function(d, i) { return i * 32; })
      .attr("dy", ".35em");

  // ENTER + UPDATE
  // Appending to the enter selection expands the update selection to include
  // entering elements; so, operations on the update selection after appending to
  // the enter selection will apply to both entering and updating nodes.
  text.text(function(d) { return d; });

  // EXIT
  // Remove old elements as needed.
  text.exit().remove();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM