修改强制布局 - 使用索引而不是引用会产生 TypeError

Modifying a Force Layout - using indexes rather than references gives TypeError

我正在开发一个简单的 D3 力导向布局,基于 Modifying a Force Layout 示例,它工作正常,使用 setTimeout 回调更新的硬编码数据:

但是,我将从服务器动态加载数据作为 JSON,因此希望将 link sourcetarget 指定为索引nodes 数组,而不是对实际 JavaScript 节点对象的引用。 documentation;

中描述了此选项

Note: the values of the source and target attributes may be initially specified as indexes into the nodes array; these will be replaced by references after the call to start.

作为第一步,我尝试修改示例以使用索引;在下面的代码片段中:

var a = {id: "a"}, b = {id: "b"}, c = {id: "c"};
nodes.push(a, b, c);
links.push({source: a, target: b},{source: a, target: c},{source: b, target: c});
start(); // joins the data, (re)starts the d3.layout.force

我只更改一行以在节点中使用索引,如下所示:

links.push({source: 0, target: 1},{source: 0, target: 2},{source: 1, target: 2});

但是,这会导致 d3.v3.min.js (Firefox 35.0.1) 出现 JavaScript 错误:

TypeError: u is undefined

并且只创建了部分图表 - 显示了所有 3 个节点,但只显示了一个 link:

可以这样使用索引吗?

不,当前强制布局的实现不可能以这种方式使用索引。当您开始布局时,链接中的所有索引都将替换为对对象的引用(这就是文档说您可以使用索引的原因,请参阅 the source 的第 223-229 行)。当您在没有(重新)启动布局的情况下推送索引时,不会发生这种替换并且代码会中断。

您有两种选择来完成这项工作——要么推送对节点对象的引用,要么在每次推送后在强制布局上调用 .start()。请注意,对于后者,您还应该在推送之前停止布局,并且所有力都将重新初始化,每次更改内容时都会使布局非常"jumpy"。

听起来在你的情况下推送对节点对象的引用而不是索引不会有问题,因为你可以访问节点数组。然后您需要做的就是对其进行索引,就像在 D3 源代码中所做的那样。