在d3力布局中自动生成链接。

时间:2023-02-02 21:06:58

Using D3.js's force layout I'm trying to make the links automatically generate based on the node data. The nodes already appear exactly as expected.

使用D3。js的力布局,我试着让链接根据节点数据自动生成。节点已经按预期显示。

The database json strings use the following format:

数据库json字符串使用以下格式:

{
 "id": 1,
 "title": "name"
}, 
{
 "id": 2,
 "title": "other name",
 "primaryDependants": 1
}

and I'm basically trying to have it say:

我试着让它说:

'for each node, check if it has a primaryDependant property, if it does then make a link between that node and the one identified as the primary dependant.'

“对于每个节点,检查它是否有一个主依赖项属性,如果有,那么它就在该节点和被标识为主依赖项的节点之间建立链接。”

however I haven't dealt with force graphs before and tutorials are few and far between so I'm really struggling with how to make any change to my code without breaking it. Currently it is based on the answer here and I use the Meteor framework if that's of any relevance.

但是,我以前没有处理过强制图,教程也很少,所以我非常纠结如何在不破坏代码的情况下对代码进行任何更改。目前它是基于答案,我使用流星框架,如果这是任何相关性。

Template.tree.rendered = function () {

  var graph = new myGraph("#svgdiv");

  Lessons.find().observe({ 
    added: function (doc) { 
      graph.addNode(doc._id, doc.title); 
    },
    removed: function (doc) { 
      graph.removeNode(doc._id); 
    }
  });

function myGraph(el) { 

  w = 1500,
  h = 1000; 

  var svg = d3.select(el) 
    .append("svg") 
    .attr("width", w)
    .attr("height", h)
    .attr("pointer-events", "all") 

    svg.append("rect") 
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("fill", "lightgrey");

  var vis = svg.append('g'); 
  var force2 = d3.layout.force(); 
  var links = force2.links(); 
  var nodes = force2.nodes(); 

  var update = function () { 

    var link = vis.selectAll("line") 
      .data(links, function(d) {return d.source.id + "-" + d.target.id;}); 

    link.enter().append("line") 
      .attr("id",function(d){return d.source.id + "-" + d.target.id;}) 
      .attr("class","link"); 

    link.append("title") 
    .text(function(d){
      return d.value;
    });

    link.exit().remove();

    var node = vis.selectAll("g") 
      .data(nodes, function(d) { return d.id;}); 

    var nodeEnter = node.enter() 
      .append("g") 
        .call(force2.drag)
      .append("circle") 
        .attr("r", 8)
        .attr("fill", "#585858")
        .attr("stroke", "#008db7")
        .attr("stroke-width", 3)
        .attr("id", function(e) { return "Node;"+e.id;})
        .attr("class", ( function(f){return f.id;}));

    node.exit().remove(); 

    force2.on("tick", function() { 
      node.attr("transform", function(g) { return "translate(" + g.x + "," + g.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; });
    });

    force2 
      .gravity(.02)
      .linkDistance( 200 ) 
      .size([w, h])
      .start();
  };

  update(); 

  var findNode = function(id) { 
    for (var i in nodes) {
      if (nodes[i]["id"] === id) return nodes[i];};
  };

  var findNodeIndex = function(id) { 
    for (var i=0;i<nodes.length;i++) {
      if (nodes[i].id==id){
        return i;
      }
    };
  };

  this.addNode = function (id, title) { 
    nodes.push({"id":id,"title":title});
    update(); 
  };

  this.addLink = function (source, target, value) {
    links.push({"source":findNode(source),"target":findNode(target),"value":value});
    update();
  }; 

  this.removeNode = function (id) { 
    var i = 0;
    var n = findNode(id);
    nodes.splice(findNodeIndex(id),1); 

    update(); 
  };
}

1 个解决方案

#1


1  

To create the links array based on your description:

根据您的描述创建链接数组:

var dataset = [{
 "id": 1,
 "title": "name"
}, 
{
 "id": 2,
 "title": "other name",
 "primaryDependants": 1
}];

var links = [];

dataset.forEach(function(d){
  if(d.primaryDependants){
    links.push({source: d.id,
                target: d.primaryDependants});
    }});

console.log(links)

#1


1  

To create the links array based on your description:

根据您的描述创建链接数组:

var dataset = [{
 "id": 1,
 "title": "name"
}, 
{
 "id": 2,
 "title": "other name",
 "primaryDependants": 1
}];

var links = [];

dataset.forEach(function(d){
  if(d.primaryDependants){
    links.push({source: d.id,
                target: d.primaryDependants});
    }});

console.log(links)