D3.js更新堆叠条形图

D3.js updating a stacked bar chart

本文关键字:条形图 更新 js D3      更新时间:2023-09-26

我基本上按照这个例子构建了一个堆叠条形图。但是,我想通过下拉菜单更新数据。

我的逻辑是这样的:我有一个由15个对象组成的JSON数组中的数据。我在Javascript中使用一个数组来存储这些对象中的每一个,当我从下拉菜单中选择一个索引时,我想加载所选对象的D3可视化。

目前,我的堆叠条形图可以工作,当我更改索引时,我可以正确地更新/动画轴,但我在显示图表时遇到了问题。出于某种原因,我必须按两次更新按钮才能显示图形,即使第一次单击时会显示轴。

我的代码是这样的:

d3.json调用

函数更新(索引){

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);

我有一种感觉,这是因为我创建了new_layer变量,也许在我第一次调用update时它还没有完全初始化,所以我需要再次按下它?不完全确定,因此任何指导都将不胜感激。

我的代码结构基本上遵循第一句中链接的示例,但d3示例没有转换。

请遵循标准更新模式:https://bl.ocks.org/mbostock/3808218

在您的情况下,如果您只想删除旧层并重新绘制它们:

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);

此外,转换是异步执行的,因此即使以后的代码是在转换之后按顺序执行的,当您到达以后的代码时,状态也可能没有被转换更新。

通用更新模式,供您参考:

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();
}
相关文章: