用g容器重绘功能

时间:2012-03-21 12:06:59

标签: d3.js

如果有人能说清楚,我有几个问题。

我写了一个d3重绘功能。代码是here。它基于示例a bar chart pt 2

我已经做到了,所以点击一个正方形会添加数据,然后调用重绘。 redraw()函数将'gBaby'容器添加到正确的'gChild'容器中,但它增加了两个而不是一个 - 这是我的第一个谜。除了这两个'rect'和'text'元素添加到同一个容器中,我知道为什么它们被添加到同一个容器中。

  1. 为什么每次只有一个元素添加到数据时会绘制两个元素?
  2. 如何在添加和更新数据时修改我的redraw()以在新gBaby容器中追加新的rect和text元素(如果数据被拼接和更新,它会删除g容器吗?)
  3. 如果数据最初是空的,通过其他方式更新并且redraw()运行,那么这会有效吗?
  4. 欢呼任何帮助 r34ch

1 个答案:

答案 0 :(得分:5)

您应该做的第一件事是使用调试器逐步执行代码,或者在JavaScript控制台中逐步运行代码(使用复制粘贴或手动输入)。通过这种方式,您可以检查整个过程中的选择,并查看出现问题的地方。

关于你的第一个问题,为什么只有一个元素添加到数据时会绘制两个元素:你知道你实际上是在向数据添加两个元素吗? Array.push采用可变数量的参数,因此data.push(50, i * 110)正如您在点击时所做的那样,将两个值添加到数组的末尾。如果要在特定索引处添加单个值,请改用Array.splice

我看到的第二个危险,但可能不是问题,是重绘时的选择器与创建时的选择器不匹配;在创作时,你说gChild.selectAll("g.baby"),但在重绘时你说gChild.selectAll("g")。在这两种情况下我都会使用selectAll(".baby")。我也会避免使用camelCased类名,因为CSS类不区分大小写,并且使用大小写会产生误导。

下一个问题是你正在进行两次数据连接,这比你只有一个数据集需要多一次。加入gChild后,您也无需加入gChild.selectAll("rect")。问题是您将帐户直接添加到gChild而不是您创建的gBaby。您需要遵循在创建时使用的模式,并附加到输入gBaby

var gBaby = gChild.selectAll(".baby")
    .data(data);

var gBabyEnter = gBaby.enter().append("g")
    .attr("class", "baby")
    .attr("transform", function(d) { return "translate(" + d + ")"; });

gBabyEnter.append("rect")
    …

gBabyEnter.append("text")
    …

gBaby.exit().remove();

我还将代码更改为使用共享转换,而不是复制x和y属性。