2012-11-30 39 views
5

我的目标是使用d3强制布局来显示共享相同节点的两个不同网络。例如,在四个人当中,你可以定义一个社交网络和一个家谱网络;节点将是相同的(人),但链接(关系)可能不同。 尽管创建了两个单独的力布局,两个单独的svg画布,并试图定义单独的变量,节点共享x和y位置信息。这里是一个小例子,在拖动一个网络上的节点改变等网络中的位置: http://amath.colorado.edu/student/larremore/nodesSharingPositiond3在同一页面上的多个d3强制布局实例

下面,我贴被称为创造了网络的一个功能,和代码来创建其他非常相似,但在所有情况下使用不同的变量名称。用于创建两个网络的注释代码可在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(); 
} 
+0

我正在尝试做同样的事情:在同一页上同步两个强制布局的节点位置。由于Alex Reynolds的回复,我有两个部队布局。但是,我没有在哪里设置位置同步的钩子。由于到DBLaremore的方法的链接不再工作,有没有人有暗示从哪里开始或可能链接到另一个例子? – tty56

回答

4

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

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

在我的情况下,我使用_left_right作为每个面板元素的足够,其中元素分别在左侧或右侧面板中。跟踪记录需要很多工作,但网络渲染器可以将其呼叫和事件定位到正确的元素和网络。

你的情况:

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

您想更换return价值的东西,唯一解决该节点关联的网络。无论您使用索引编号方案还是基于后缀的方法(如我一样),诀窍在于确保所有名称都是唯一的。

+0

你的网站的例子是一个很好的模仿 - 看起来很棒!但是,我无法通过更改ID来解决我的问题。我尝试过使用不同的ID,以及没有ID,并且在这两种情况下,显示屏仍然互相更新。我已经检查过左侧(X)和右侧(Y)的名称在布局,节点,链接和svg画布的名称上有所不同。还有其他建议吗?我不知道这是否相关,但如果您拖动并保持一个网络足够长的时间,另一个网络会冷却/冻结,然后不再链接(显然)。 – DBLarremore

+0

我不知道还有什么可行的。我确实知道,确保每个网络中的每个元素都是唯一的,这是做这项工作的关键。如果有任何重复的'id'名称,事情就会中断。希望我能更多的帮助! –

+0

我注意到的另一件事(可能)提供了一条线索: 经过一段时间/耗散后,布局将冻结当前位置的节点。如果您抓住左侧布局并左右移动,直到右侧冻结,您将无法间接移动右侧布局。然后,如果您抓住正确的布局,则只能使用它来影响左侧的**,直到左侧冻结。对我而言,这意味着虽然布局的位置可能受到影响,但制冷计时器不受该运动的影响。节点在两个图中移动,但只有一个寄存器动态。 – DBLarremore

0

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

没有一个真正的副本,所产生的行为会有点乱,因为你发现,这取决于D3代码是否据法权产修改任何共享数据“原位”还是不。一般来说,出于性能原因,D3尝试而不是来创建副本。

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