Невозможно нарисовать ссылки по свойству узла, используя раскладку D3 - PullRequest
0 голосов
/ 05 мая 2018

Я пытаюсь сделать принудительное расположение на 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

Кроме того, при этом узлы не будут вести себя так, как ожидалось на макете (набор радиальных сил не будет работать, см. Прикрепленные изображения), предполагая, что этот атрибут ссылка-на-узле мешает моему моделированию.

Not broken layout, but without adding the forceLinks Layout broken after trying to add links

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
...

links.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. enter image description here

Есть идеи?

1 Ответ

0 голосов
/ 05 мая 2018

Вот конструктивная критика: правильно сделайте отступ в вашем коде 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.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, они просто возвращают тот же объект, который вы имели бы без них ).

Вот блокс с вашим кодом и данными, используя Promise.all:

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


1 Большинство текстовых редакторов, таких как Sublime Text, имеют плагины для отступов. Вы также можете найти несколько хороших инструментов онлайн, например, , например этот .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...