多个d3实例在同一页面上强制布局

时间:2012-11-30 17:44:42

标签: layout d3.js multiple-instances force-layout

我的目标是使用d3 force布局显示共享相同节点的两个不同网络。例如,在四个人中,您可以定义社交网络和家谱网络;节点将是相同的(人),但链接(关系)可能是不同的。 尽管创建了两个单独的力布局,两个独立的svg画布,并尝试定义单独的变量,但节点共享x和y位置信息。这是一个最小的示例,其中一个网络上的拖动节点发生变化他们在其他网络中的位置: http://amath.colorado.edu/student/larremore/nodesSharingPositiond3

下面,我发布了调用创建其中一个网络的函数,创建另一个网络的代码非常相似,但在所有实例中使用不同的变量名。用于创建两个网络的注释代码可以在http://amath.colorado.edu/student/larremore/nodesSharingPositiond3/lib/minimal.js中找到,用于定义变量的脚本可以在/driver/minimalScript.js中找到< - 我没有足够的声誉来直接链接它。我道歉!

d3.force工作的某个方面,位置信息是全局的或全球选择的,或者某种东西。有人能说清楚这个吗?我对保持位置信息分离的解决方案以及理解d3.force如何处理和更新位置计算感兴趣。

function makeYNet() {

// This populates the YactiveLinks variable with the proper YLinks. The goal is to be able to only display links whose value is above some threshold.
for (var i=0; i<YLinks.length; i++) {
    if (YLinks[i].link2 > thr) {
        YactiveLinks.push(YLinks[i]);
    }
}

// Add nodes and links to forceY
forceY
.nodes(YNodes)
.links(YactiveLinks);

// Draw lines
var Ylink = svgY.selectAll("line.link")
.data(YactiveLinks)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", 2.0);

// Draw nodes
var Ynode = svgY.selectAll("circle.node")
.data(YNodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", radius)
.attr("high",0)
.attr("id", function(d,i) {
      return ("idy" + i);
      })
.style("fill", function(d) { return color(d.group1); })
.call(forceY.drag)
;

// Define tick 
forceY.on("tick", function() {
          Ylink
          .attr("x1", function(d) { return d.source.x; })
          .attr("y1", function(d) { return d.source.y; })
          .attr("x2", function(d) { return d.target.x; })
          .attr("y2", function(d) { return d.target.y; });

          Ynode.attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; });
          });

// Start 'er up
forceY.start();
}

2 个答案:

答案 0 :(得分:4)

我写了一个工具,允许浏览生物regulatory networks,并排显示两个SVG面板。每个面板都包含一个强制布局网络,由d3.js API绘制。

我发现做这项工作的关键是给DOM中的每个元素一个唯一的名称,在那里可以有重复。

就我而言,我使用_left_right作为每个面板元素的足够的元素,其中元素分别位于左侧或右侧面板中。要跟踪这项工作需要做很多工作,但网络渲染器可以将其调用和事件定位到正确的元素和网络。

在你的情况下:

.attr("id", function(d,i) {
      return ("idx" + i);
      })

您希望将return值替换为唯一地址与节点关联的网络的内容。无论您使用索引编号方案还是基于后缀的方法,就像我一样,诀窍是确保所有id名称都是唯一的。

答案 1 :(得分:0)

Javascript因混淆状态是否共享而臭名昭着。你的最小例子不再可用了,但当我遇到同样的问题时,我的结论是我只是在需要完整克隆的地方制作浅拷贝。 (我正在谈论D3作为输入的链接和节点。)

如果没有真正的副本,结果行为会有点随机,正如您所发现的那样,取决于D3代码是否选择修改任何共享数据&#34; in situ&#34;或不。通常,出于性能原因,D3会尝试而不是来创建副本。

这就是json调用解决方法的工作原理:通过完全字符串化所有数据,您事实上强制执行克隆操作。