d3中的动态更新适用于圆圈但不适用于外部SVG

时间:2013-09-07 22:11:54

标签: javascript d3.js

假设我想使用d3动态更新页面上的圆圈位置和数量。我可以使用.data(),. enter(),. exit()模式来完成此操作。这是一个有效的例子。 http://jsfiddle.net/csaid/MFBye/6/

function updatePositions(data) {

  var circles = svg.selectAll("circle").data(data);

  circles.enter().append("circle");

  circles.exit().remove();

  circles.attr("r", 6)
      .attr("cx", 50)
      .attr("cy", function (d) {
      return 20 * d
  });

}

但是,当我尝试使用外部SVG而不是圆圈执行相同操作时,第一次更新后的许多新数据点都不会显示在页面上。例: http://jsfiddle.net/csaid/bmdQz/8/

function updatePositions(data) {

    var gs = svg.selectAll("g")
        .data(data);

    gs.enter().append("g");

    gs.exit().remove();

    gs.attr("transform", function (d, i) {
        return "translate(50," + d * 20 + ")";
    })

        .each(function (d, i) {
        var car = this.appendChild(importedNode.cloneNode(true));
        d3.select(car).select("path")
    });
}

我怀疑这与用于附加外部SVG对象的.each()有关,但我对如何解决这个问题感到茫然。此外,“cx”和“cy”属性是特定于圆圈的,因此我无法想象它们如何用于外部SVG。

提前致谢!

1 个答案:

答案 0 :(得分:0)

您的代码存在两个问题。第一个问题以及您没有看到所有数据点的原因是您的外部SVG包含您正在选择的g个元素。这意味着,在您首次添加元素之后,任何后续.selectAll("g")选项都将包含来自这些外部SVG的元素。这反过来意味着您传递给.data()的数据与那些数据匹配,因此您的选择不包含您的期望。通过向您明确添加的g元素添加一个类并相应地进行选择,可以轻松解决此问题。

第二个问题是您正在执行将外部SVG作为更新选择的一部分附加的代码。这意味着这些元素会被多次添加 - 不是你会注意到的(因为它们重叠),但也不是可取的。通过移动调用以将节点克隆到.enter()选择,可以轻松解决此问题。

完成jsfiddle here。至于您关于cxcy的问题,您并不真正需要它们。您可以使用transform属性设置您追加的任何元素的位置,就像您在代码中已经做的那样。