D3.js无法更新数据。

6
我正在使用AngularJS更新一个D3堆叠条形图。在此过程中,所有数据最初都是可见的,并且更新会筛选掉不需要的数据。过去,使用以下模型一直可以正常工作:
data = [{
    name: John Doe, 
    splits: [{distance: 1, time: 1234},]
},...]

现在我正在尝试使用这个模型为每个堆栈添加一个额外的条形图:
data = [{
    name: John Doe
    time: 12345, 
    splits: [{distance: 1, time: 1234},]
},...]

我的问题是更新数据。我的计算值被正确地重新计算,例如用于缩放的域。一个用于时间更新的行仍然只能识别更新前的数据值(代码片段已经大幅缩短):
// Set ranges of values in axes
x.domain(data.map(function(d) { return d.name}));
y.domain([ min , max]);

// Y Axis is updated to the correct time range
chart.append('g').attr('class', 'y axis').call(yAxis).selectAll('text').style('font-family','Open Sans').style('font-size', '.9rem'); 

// data join / Select Athlete
var athlete = chart.selectAll(".athlete").data(data),
athdata = athlete.enter(),

console.log(data) // data is correct here

// add container for each athlete
athplace = athdata.append("g")
  .attr("class", "athlete")
  .attr("transform", function(d) {  return "translate(" + x(d.name) + ",0)"; })
  .text(function(d) { return d.name}),

// ENTER time
athplace.append('rect')
.attr('class', "time")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.time.time); })
.attr("height", 0).transition().duration(300)
.attr("height", function(d) {  return height-y(d.time); });

... enter splits & labels

// exit splits & athlete
splitlabels.exit().transition().duration(300).attr('opacity', 0).remove();
splits.exit().transition().duration(300).attr('height', 0).attr('opacity', 0).remove();
athlete.exit().transition().duration(300).attr('width',0).attr('opacity', 0).remove();

console.log(athlete) // data is still correct

// UPDATE time, this chain has the problem with data not being updated. "d" is equal to previous values
athlete.selectAll('rect.time')
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.time.time); })
.attr("height", function(d) {  return height-y(d.time); });

由于这些错误,更新的列代表了错误的数据并生成了错误的可视化。我一整天都在盯着/测试这个问题,试图将问题隔离到现在的程度。有没有更有经验的D3人士能给我一些见解?
注意:对于那些感兴趣的人,这全部都是在Angular指令中完成的,我会$watch数据值的变化,尽管我100%确定这不是问题所在。
编辑
这里是一个JSFiddle,展示了与我的脚本中相同的错误。所有代码都是从出现问题的脚本直接提取的。底部的间隔更新模拟了通常会发生的数据交换。

你有一个 JSFiddle 吗? - vittore
现在正在制作一个小提琴。 - DFenstermacher
我在问题底部刚刚添加了一个JSFiddle。 - DFenstermacher
1个回答

2

我使用了你的例子,并作了一些更改,可能会有所帮助。

首先,我将顶部的全局 var 移到了 update 函数内部进行重构。通过这样做,我们就不会在我们的 xy 轴继续向下时“双重添加”,这似乎会在旧图表上绘制我们的新图表。

然而,修复了这个问题之后,我得到了新的图表覆盖在旧的图表上的情况。为了解决这个问题,在 update 内部调用 d3.selectAll("svg > *").remove(); 来删除所有附加的 SVG 元素和分组,给我们一个“干净的状态”来渲染我们的新图表。这解决了覆盖问题。

你提到这是为了简洁起见而缩短的,所以我希望这个例子能对你实际的应用有所帮助。


更新的 Fiddle


小提琴实际上比我包含的代码片段更接近我的实际实现。你的示例完全达到了我希望图表实现的效果。感谢您抽出时间解决这个问题! - DFenstermacher
嗨,我也遇到了同样的问题。我从服务器获取了新数据,其中包含新的轴和其他属性,数据已经成功加载,并且在日志记录中,显示的数据符合预期。然而,在图表的更新块上,它仍然使用旧数据进行绘制。无法使用最新数据。我也通过首先从图表中删除“g”节点,然后重新绘制来解决了相同的问题。这是什么情况,我们需要先删除节点,才能在没有节点的情况下更新元素?谢谢。 - Manish Kumar
你已经发布了问题吗?我鼓励您尽可能提供所有细节,包括一个能够重现问题的工作示例。从您上面的回复中,我没有足够的信息来提出建议,但如果您撰写一个问题并在此处分享链接,我很乐意查看。 - scniro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接