【问题标题】:Can't draw links by node property using D3 force layout无法使用 D3 强制布局按节点属性绘制链接
【发布时间】:2018-05-05 01:50:41
【问题描述】:

我正在尝试在 D3 上进行强制布局,以使用节点和链接进行网络可视化。我一直在使用 v3,但我切换到 v5 以便能够使用节点属性而不是节点索引来链接节点(这需要 d3 v3 中的额外步骤)。

我得到了这个代码

https://jsfiddle.net/lioneluranl/4fxpp2co/1/

var linkpath = ("links.csv");
var nodepath = ("nodes.csv");
var svg = d3.select("svg");
var width = svg.attr("width");
var height = svg.attr("height");
var simulation = d3.forceSimulation();   

var nodes = [];
var links = [];

d3.csv(nodepath, function(d){
  node = {
    id: d.node,
    group: d.group,
    node: d.node
  };  

  nodes.push(node);

  d3.csv(linkpath, function(d){
    link = {
      source: d.source,
      target: d.target,
      type: d.type
    }; 

    links.push(link);

  });

}).then( function() {

  //console.log(links);
  //console.log(nodes);

  simulation
      .force("link", d3.forceLink().id(function(d) { /*console.log(d);*/ return d.id; }))
      .nodes(nodes)      
      .force("collide", d3.forceCollide().radius(10))
      .force("r", d3.forceRadial(function(d) { 
        if(d.group === "compound"){          
          return 240;
        } else { return d.group === "annotation" ? 0 : 100; }}))      

  // Create the link lines.
  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)
    .enter().append("line")
    .attr("stroke", "black")
    .attr("stroke-width", 4)
    .attr("class", function(d) { return "link " + d.type; });

  // Create the node circles.
 var node = svg.append("g")
      .attr("class", "node")
      .selectAll("circle")
      .data(nodes)
      .enter().append("circle")
      .attr("r", 8)
      .attr("class", function (d){ 

        return d.group;

      });

 simulation.on("tick", ticked);
 simulation.force("link").links(links);

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

  link.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; });
}


}); 

改编自此

https://bl.ocks.org/mbostock/cd98bf52e9067e26945edd95e8cf6ef9

绘制节点没有问题,但无法绘制链接。相关文档表明,正如我认为我正在做的那样,节点属性必须传递给力模拟的链接,但我收到此错误:

TypeError: can't assign to property "vx" on "PF05257": not an object

此外,执行此操作时,节点在布局上的行为不会像预期的那样(径向力设置不起作用,请参见附图),这表明此逐节点属性与我的模拟相混淆。

CSV 包含以下数据:

nodes.csv:

node,group
C236103,compound
C327961,compound
C337527,compound
C376038,compound
C543486,compound
T24871,target
T27222,target
T33516,target
T33937,target
OG5_135897,annotation
PF01529,annotation
PF05257,annotation
PF11669,annotation
...

链接.csv

source,target,type
T24871,PF05257,annotation
T27222,PF05257,annotation
T33516,PF01529,annotation
T33516,PF05257,annotation
T33516,PF11669,annotation
T33937,PF05257,annotation
T24871,C561727,bioactivity
T24871,C337527,bioactivity
T24871,C585910,bioactivity
...

仅用于参考和数据完整性完整性检查,我在 d3 v3 上进行了此操作。

有什么想法吗?

【问题讨论】:

    标签: javascript d3.js promise


    【解决方案1】:

    这是一个建设性的批评:正确缩进你的代码1

    我第一次阅读时错过了这个问题,因为缩进不正确。但是,有了正确的缩进,问题就很清楚了,看看这个:

    d3.csv(nodepath, function(d) {
        node = {
            id: d.node,
            group: d.group,
            node: d.node
        };
    
        nodes.push(node);
    
        d3.csv(linkpath, function(d) {
            link = {
                source: d.source,
                target: d.target,
                type: d.type
            };
    
            links.push(link);
    
        });
    })
    

    你不能像这样嵌套d3.csv。您的代码现在的方式是第二个d3.csv 是第一个d3.csv 的行函数的一部分,这显然行不通。

    这里的正确方法是嵌套 Promise(这对某些人来说是一种反模式),或者更好的是使用 Promise.all(因为在 v5 中没有 d3.queue):

    var promises = [d3.csv("nodes.csv"), d3.csv("links.csv")];
    
    Promise.all(promises).then(function(data) {
        var links = data[1];
        var nodes = data[0];
        //rest of the code here
    });
    

    作为附加提示,您无需将对象推送到外部范围内的数组:只需处理 then 内的参数即可。

    此外,您不需要两个 CSV 的行函数,因为您的行函数现在没有做任何事情(除了将 node 复制为 id 之外,它们只是返回相同的对象,没有它们)。

    这是一个包含您的代码和数据的 bl.ocks,使用 Promise.all

    https://bl.ocks.org/GerardoFurtado/30cb90cc9eb4f239f59b323bbdfe4293/3049fc77b8461232b6b149f39066ec39e0d111c1


    1 大多数文本编辑器,例如 Sublime Text,都有缩进插件。您还可以在网上找到几个不错的工具,例如like this one

    【讨论】:

    • 快照...非常感谢!我会继续测试它。很抱歉 de 缩进问题。我使用了 Jsfiddle 美化功能,但并没有真正检查它是否正确缩进。
    猜你喜欢
    • 1970-01-01
    • 2018-09-20
    • 2014-08-01
    • 1970-01-01
    • 2014-10-18
    • 2014-07-22
    • 1970-01-01
    • 2015-05-23
    相关资源
    最近更新 更多