【问题标题】:d3.js chart not updated with new datad3.js 图表未使用新数据更新
【发布时间】:2026-01-11 09:15:02
【问题描述】:

使用d3.js 通过获取包含 100 个对象的数组来绘制一系列矩形。尽管console.log(data) 显示正在检索新数据,但新数据点似乎没有附加任何矩形。

.enter().append() 使用不当?

function init() {
    var width = 800,
        height = 400,
        margin = 50;

    chart = d3.select('#chart')
                .append('svg:svg')
                .attr('width', width)
                .attr('height', height);
}

function do_update() {
    data = fetch_latest_top100();
    console.log(data)

    chart.selectAll('rect')
        .data(data)
        .enter()
        .append('svg:rect')
        .attr('x', function(d) { return x(d.x); })
        .attr('y', function(d) { return y(d.y); })
        .attr('height', function(d) { return d.value; })
        .attr('width', function(d) { return 3 });
}

jsfiddlehttp://jsfiddle.net/BU8cA/

【问题讨论】:

  • 最好包含一个小提琴 (jsfiddle.net) 或 plunkr plnkr.co/edit/?p=catalogue,这将有助于实时查看问题
  • 我不知道这是否是复制/粘贴问题,但您在 y 属性上的 y(d.y 之后缺少“)”,这可能是错误
  • @tomtomtom 复制粘贴问题,纠正错字,谢谢!
  • 尝试删除 svg: 在 rect 之前,因为您已经在选择 svg,如下所示: .append("rect") 如果不是我没有看到任何其他奇怪的东西代码
  • @tomtomtom 我在帖子中包含了 jsfiddle。第二次获取的数据似乎对图表没有任何作用。

标签: javascript jquery svg d3.js


【解决方案1】:

您的更新方法的问题在于它只处理新元素,而不更新现有元素以匹配它们的新数据。使用 enter() 选择创建新矩形后,您必须返回完整的选择(新的和更改的矩形)以设置将要更改的属性。

执行此操作的最简单方法是将选择存储在一个变量中,在您应用数据函数但在调用 enter 方法之前,如下所示:

   var rects = chart.selectAll('rect')
        .data(data);

   rects.enter()
        .append('svg:rect')
        .attr('width', function(d) { return 3 }); 
       // since the width is constant, you only need to set it once

   rects.exit().remove(); //if the number of data points might shrink

   rects.attr('x', function(d) { return x(d.x); })
        .attr('y', function(d) { return y(d.y); })
        .attr('height', function(d) { return d.value; });
   //note that this now includes the rectangles created with enter()
   //as well as the old ones you are resizing / repositioning

这应该得到正确的数据,但你仍然有一个布局问题(无论如何,在小提琴上),因为你的 y 值没有被正确设置。 y 值是矩形顶部的位置,因此,如果您希望条形看起来都位于同一条线上,则需要根据条形的高度对其进行调整。 Mike Bostock 的教程和演示在这里:http://bost.ocks.org/mike/bar/3/


D3 版本 4+ 的更新

附加到“输入”选择的元素不再自动添加到主(更新)选择。您现在需要通过在“输入”选择上调用merge 方法来显式创建“合并”选择:

var rects = chart.selectAll('rect')
    .data(data);

rects.exit().remove(); //if the number of data points might shrink

rects.enter()
    .append('svg:rect')
    .attr('width', function(d) { return 3 }) // since the width is constant, you only need to set it once

  .merge(rects) 
          //merge the newly added elements into the main selection
          //of existing elements to update
    .attr('x', function(d) { return x(d.x); })
    .attr('y', function(d) { return y(d.y); })
    .attr('height', function(d) { return d.value; });

【讨论】:

  • 这个答案还有效吗?如果我在调用 rects.enter().append() 之后调用 rects.nodes(),我仍然会得到一个空数组。如果上面声称“这现在包括使用 enter() 创建的矩形”是真的,我不应该期望在调用 .nodes() 时看到一个填充数组,而不是一个空数组吗?
  • @mevans 您在使用 D3 v4 吗?它极大地改变了合并的工作方式,请参阅Mike Bostock's overview of the reasoning behind the changes。您现在需要显式调用selection.merge() 来组合输入和更新选择。
  • 是的 - 我正在使用 D3 v4。 .merge() 的引入和 enter/update 的更改(现在的功能与网络上的大多数示例相反)令人抓狂。非常感谢您的澄清。
  • @AmeliaBR 你能看看这个问题并帮助解决*.com/questions/39998877/…