如何在d3中更新带有附带文本的条形图

How to update a bar chart with accompanying text in d3?

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

我正在创建一个条形图,作为d3中更大数据可视化的一部分。我希望能够更改可视化的一部分中的数据,所有图表都将更新。图表的简化版本如下。

var dataset = [1, 3, 5, 3, 3];
...
var svg = d3.select("body #container").append("svg")
        .attr("width", width)
        .attr("height", height);
    var g = svg.append("g");
...

我用这个svg元素创建了其他图表,比如地图、圆圈等。条形图是这样实现的。

 function bars(dataset) {
      var barChart = g.selectAll("rect.bar")
        .data(dataset)
        .enter();
      barChart.append("rect")
        .attr("class", "bar")
        .attr("x", function(d, i) { return i * 30 + 100; })
        .attr("y", function(d) { return (height - 130) - d * 4;})
        .attr("width", 25)
        .attr("height", function(d) { return d * 4; });

       barChart.append("text")
        .text(function(d) { return d; })
        .attr("x", function(d, i) { return i * 30 + 103; })
        .attr("y", function(d) { return (height - 130) - d/10 - 5;})
        .attr("font-family", "sans-serif")
        .attr("font-size", "10px")
        .attr("fill", "darkgray"); 
}

现在,这使条形图很好,但有一个功能

...
.on("click", function() {
   ...
   var newdata = [5, 2, 6, 2, 4]; // new values
   g.selectAll("rect.bar").remove();  // This removes the bars
   g.selectAll("text").remove();    // Problem here: All texts are removed
   bars(newdata);
}

我试着用.remove()函数将条形图转换为新值。这适用于条形图,因为没有其他条形图,但当我试图删除上面显示的值标签时,所有其他文本元素也被删除了。有没有办法只更新与条形图关联的文本?

您是否尝试过将类应用于文本并只选择要删除的类?例如

barChart.append("text")
  .attr('class','label')
  .text(function(d) { return d; })

然后

g.selectAll(".label").remove();

顺便说一句,如果在更新之间没有删除所有元素,那么您是否考虑过使用enter()exit()将新数据绑定到现有元素,只删除正在更改的元素,而不是删除所有元素?

编辑像这样:

function bars(dataset) {
  var bar = g.selectAll(".bar").data(dataset);
  bar.exit().remove();
  bar.enter().append("rect").attr("class", "bar");
  bar
    .attr("x", function(d, i) { return i * 30 + 100; })
    .attr("y", function(d) { return (height - 130) - d * 4;})
    .attr("width", 25)
    .attr("height", function(d) { return d * 4; });
  var label = g.selectAll(".label").data(dataset);
  label.exit().remove();
  label.enter().append("text").attr("class", "label");
  label
    .text(function(d) { return d; })
    .attr("x", function(d, i) { return i * 30 + 103; })
    .attr("y", function(d) { return (height - 130) - d/10 - 5;})
    .attr("font-family", "sans-serif")
    .attr("font-size", "10px")
    .attr("fill", "darkgray"); 
}