【问题标题】:Why is data not updating correctly on this D3.js barchart?为什么此 D3.js 条形图上的数据未正确更新?
【发布时间】:2014-06-21 06:16:34
【问题描述】:

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

根据 Mike Bostock 的 Let's Make a Bar Chart 教程,bar 的结构如下,一个 rect 和一个 text 元素(分别表示 bar 及其标签)嵌套在 g.bar 元素中,所有 g.bar在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() 模式吗?我怎样才能解决这个问题?谢谢!

【问题讨论】:

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


    【解决方案1】:

    一旦你读了这篇文章,你就不会相信这个错误是多么愚蠢和多么令人讨厌。


    观察

    为了方便,这里是jsfiddle的原代码版本。

    如果您使用它的时间足够长,您会注意到有问题的情况是那些条形的值(高度)在不同年份相同的情况(它们可能针对不同的国家/地区)。例如,值 44 在 2012 年和 2009 年都被提及,当我们从 2012 年切换到 2009 年或反之时,我们就会遇到您描述的问题。

    此外,如果一个值在同一年被提及两次,则两个对应的条将丢失一个!

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

    实际上,问题在于在 enter() 之后调用 data()!

    关于data() 的文档说第二个参数应该是关键!不是您传递的值!这从上面解释了行为。每当值重复时,d3 会将其解释为新数据或现有数据的相同键,并且会使您的条形图变得一团糟!

    解决方案

    代替

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

    使用

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

    你的问题就会消失!

    这里是jsfiddle,代码已更正 - 工作起来很迷人!


    【讨论】:

      【解决方案2】:

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

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

      ...然后应用它:

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

      这里有一个PLUNK 来说明这一点。

      【讨论】:

      • 是的,没问题,很高兴见到你! @蕨
      • @VividD 从这里开始!感谢您对此question 的帮助。
      • 嘿,@Fern,我不想听起来我在分裂头发,但是:2007 年 - 你的解决方案没有修复错误 - 克罗地亚和斯洛伐克具有相同的值 12,但斯洛伐克吧不见了! (如果您将两个国家/地区的 12 更改为 120,您会看得更清楚);)也许我们两种解决方案的结合是可行的方法!我们可以分点吗? :) ;)
      • @VividD 确实,您对数据键控部分的看法是完全正确的。很棒的收获。两个答案都很好地服务于 OP。
      • 我们是梦之队! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      • 2018-05-09
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 2013-06-26
      相关资源
      最近更新 更多