为什么数据在此D3.js条形图上无法正确更新?

时间:2014-05-05 03:00:49

标签: javascript json d3.js transition bar-chart

我已经建立了一个比较几年数据的D3.js条形图。 This is a demo

根据Mike Bostock的Let's Make a Bar Chart教程,条形结构如下所示,其中嵌套在g.bar元素中的rect和text元素(表示条形图及其标签为repsectively),所有g.bars都在g.chart中。

<g class="chart" transform="translate(45,10)">
    <g class="bar" transform="translate(0,0)">
      <rect style="fill: rgb(117, 220, 205); stroke-width: 0.5; stroke: rgb(255, 255, 255);"  height="2.0673635307781666" width="56.9547619047619" y="116.5993031358885">
      <text class="total" y="111.5993031358885" x="28.47738095238095" text-anchor="middle" alignment-baseline="middle" style="stroke: none; fill: rgb(51, 51, 51); font-size: 0.5em; font-weight: bold; display: none;">60</text>
    </g>
    <g class="bar" transform="translate(0,0)">
        <rect style="fill: rgb(117, 220, 205); stroke-width: 0.5; stroke: rgb(255, 255, 255);"  height="2.0673635307781666" width="56.9547619047619" y="116.5993031358885">
        <text class="total" y="111.5993031358885" x="28.47738095238095" text-anchor="middle" alignment-baseline="middle" style="stroke: none; fill: rgb(51, 51, 51); font-size: 0.5em; font-weight: bold; display: none;">60</text>
    </g>
    ...
</g>

每个g.bar应该只有一个rect和一个嵌入其中的文本元素。在测试我的图表时,我注意到有些出口似乎没有正常发生。您必须通过使用Firebug或Chrome开发工具检查demo来重现这一点,但在更改一年或确实加载图表而不更改年份后,每个g.bar包含多个rect和text元素。 我没有正确实现enter()exit()remove()模式吗?我怎样才能解决这个问题?谢谢!

2 个答案:

答案 0 :(得分:2)

您只想在.enter选项中添加rects和text。因此,您必须捕获输入选择,然后在附加rects和text时使用它。像这样:

var barsEnter = bars.enter()
    .append("g")
    .classed("bar",true);

...然后应用它:

barsEnter.append("rect")
...
barsEnter.append("text")
...

以下是PLUNK说明这一点。

答案 1 :(得分:1)

一旦你读完这篇文章,你就不会相信这个愚蠢有多愚蠢和多么讨厌。


观察

为方便起见,这是原始代码的jsfiddle版本。

如果你玩的时间足够长,你会注意到有问题的案例是那些不同年份的酒吧价值(高度)相同的案例(它们可能针对不同的国家)。例如,在2012年和2009年都提到了44值,当我们从2012年切换到2009年时,反之亦然,我们遇到了您所描述的问题。

此外,如果在同一年提到两次值,两个相应的酒吧中的一个将会丢失!

这使我们得出结论,绑定数据并不完全正确。

而且,实际上,问题是在输入()之后调用data()!

关于data()的文档说第二个参数应该是关键!不是你传递的价值!这解释了上面的行为。每当值重复时,d3会将此解释为新数据或现有数据的相同键,并且会使您的酒吧变得混乱!

解决方案

而不是

.data(json[year], function(d){return d;});

使用

.data(json[year], function(d, i){ return [year, d, i]; });

你的问题就会消失!

以下是jsfiddle,其中包含更正的代码 - 像魅力一样工作!