【问题标题】:Trying to understand this d3 force example试图理解这个 d3 force 例子
【发布时间】:2014-03-20 09:57:34
【问题描述】:

我正在尝试创建一个 d3 力图,其中动态添加(然后删除)节点。 This example 大致完成了我想要的,但我无法适应它,因为 cmets 相当稀疏。

我的主要问题是关于start() 函数:

function start() {
  link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; });
  link.enter().insert("line", ".node").attr("class", "link");
  link.exit().remove();

  node = node.data(force.nodes(), function(d) { return d.id;});
  node.enter().append("circle").attr("class", function(d) { return "node " + d.id; }).attr("r", 8);
  node.exit().remove();

  force.start();
}

首先,link = link.data(force.links(), function(d) { return d.source.id + "-" + d.target.id; }); 到底在做什么?仅制作静态布局的示例使用此样式:

link = svg.selectAll("line")
    .data(links)
    .enter()
    .append("line")
    .attr("class", "link");

该代码是否与start() 中的前两行相同? (第 4..6 行似乎更接近这种风格,所以,为什么他们使用不同的方法(insertappend)?)

而且,为什么第 2 行在处理链接而不是节点时引用.node

我的最后一个问题是,像这样继续拨打force.start() 是否安全?例如,如果 start() 被调用 100 次,相隔 10 毫秒,那有关系吗?它会导致对 tick 函数的任何额外调用吗? (我只是想知道我是否应该在 start() 的顶部调用 force.stop() )? (API docs d3.layout.force 没有明确说明。)


额外问题:这些行真的有什么作用吗?

var node = svg.selectAll(".node"),
  link = svg.selectAll(".link");

由于此时没有节点,它们是否等同于:

var node,link;

【问题讨论】:

    标签: javascript d3.js force-layout


    【解决方案1】:

    关于您的第一个问题,此代码正在更新绑定到表示链接的 DOM 元素的数据。也就是说,我们采用现有的选择link(包含到目前为止的所有链接)并在其上调用.data().data() 的第二个参数告诉 D3 如何确定一个 DOM 元素是否代表一个数据元素——在这种情况下,它们通过源 ID 和目标 ID 链接。

    然后将这个新选择(旧选择 + 新数据绑定)分配回 link,以便变量再次包含链接元素的选择,但现在包含新数据。然后我们可以为.enter() 选择添加新元素,从.exit() 选择中删除元素并更新其余部分。

    您发布的静态示例中的代码再次显式选择所有元素 (svg.selectAll("line")),而不是之前使用选择集。另一个区别是它只对.enter() 选择起作用。这对于静态版本很好,因为您只需添加一次链接而不修改它们,但在您的情况下,您还需要处理其他选择。

    添加新链接的代码使用.insert("line", ".node") 而不是.append() 只是为了保持元素的相对顺序。 SVG 元素按照它们定义的顺序呈现,因此在节点之后添加的链接会出现在节点前面。通过使用.insert("line", ".node"),您告诉D3 在第一个.node 元素之前插入一个新的line 元素。也就是说,在 DOM 中的第一个节点之前添加任何新链接,以便没有节点被线条遮挡。

    一般来说,您可以随意拨打force.start() 多次和多次拨打电话是安全的。它在这种情况下所做的只是重置导致布局减慢并最终稳定的冷却参数。除非布局已经完全冷却下来,否则它不会导致对 tick() 函数的任何额外调用(不过这不会是问题)。

    您最后提到的行具有将变量建立为(可能为空的)选择的效果。这意味着您可以将它们与 .data() 等 D3 方法一起使用以将新数据绑定到它们(实际上在示例中使用了这种方法)。仅仅声明变量不会做同样的事情,因为它没有分配 D3 选择。在这种情况下,选择为空的事实并不重要。

    【讨论】:

      猜你喜欢
      • 2013-05-07
      • 2019-08-17
      • 2019-09-06
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多