javascript - 试图理解这个 d3 force 示例

标签 javascript d3.js force-layout

我正在尝试创建一个 d3 力图,其中动态添加(然后删除)节点。 This example大致按照我的意愿行事,但我在调整它时遇到了麻烦,因为评论相当稀疏。

我的主要问题是围绕 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 行似乎更接近这种风格,所以,为什么他们使用不同的方法(insert vs. append)?)

而且,为什么第 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;

最佳答案

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

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

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

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

一般来说,调用force.start() 的次数和频率都是安全的。它在这种情况下所做的只是重置导致布局减慢并最终稳定下来的冷却参数。除非布局已经完全冷却下来,否则它不应该导致对 tick() 函数的任何额外调用(尽管这不是问题)。

您在末尾提到的行具有将变量建立为(可能为空)选择的效果。这意味着您可以将它们与 D3 方法一起使用,例如 .data() 以将新数据绑定(bind)到它们(实际上在示例中使用了这一点)。只是声明变量不会做同样的事情,因为它不会分配 D3 选择。在此上下文中,选择为空这一事实无关紧要。

关于javascript - 试图理解这个 d3 force 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22529260/

相关文章:

javascript - THREE.JS更新透视相机的fov值并保持相同的相机距离

javascript - D3.js图表​​调用并缩放后重新绘制区域

javascript - 表排序器和搜索

javascript - Esprima 解析器工作示例

javascript - D3 V5 条形图

javascript - 过滤掉节点并将其置于非事件状态

d3.js 强制布局不运行

javascript - D3 布局 : Tree-like Structure, 但链接长度不同

javascript - 并行使用 async/await,并在结果到达时获取结果?

javascript - D3,具有 setInterval 和clearInterval 以及事件处理程序的 javascript 函数范围