在D3的情况下,我可以在json文件中绘制一个只有链接的图吗

Can i plot a graph with only links in a json file in case of D3?

本文关键字:一个 链接 绘制 情况下 D3 我可以 json 文件      更新时间:2023-09-26

我想从JSON文件中的链接数据中获得一个节点列表。稍后我想绘制一个带有链接和边的图。

我的示例json文件:

{
    "links": [
        { "source":0, "target":1, "value":20, "orientation":"down" },
        { "source":1, "target":2, "value":1, "orientation":"left" },
        { "source":2, "target":3, "value":1, "orientation":"right" }
    ]
}

我的JS函数:

$(function() {
    var width = 500,
        height = 300;
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);
    var force = d3.layout.force()
        .gravity(.05)
        .distance(100)
        .charge(-100)
        .size([width, height]);
    d3.json("test_1.json", function(error, json) {
        if (error) throw error;
        var count = 0;
        var nodes = [];

        json.links.forEach(function(e) { 
            count++;
            nodes.push({name: "test_"+e.source, orientation: e.orientation});
        });
        console.log("Count is :  "+count);  

        force
            .nodes(json.nodes)
            .links(json.links)
            .start();
        var link = svg.selectAll(".link")
            .data(json.links)
            .enter().append("line")
            .attr("class", "link");
        var node = svg.selectAll(".node")
           .data(json.nodes)
           .attr("class", "node")
           .call(force.drag);
        node.append("circle")
           .attr("class", "node")
           .attr("r", 5);

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

不过,我无法从函数中获得列表,因为JSON的forEach方法似乎有错误。

有人能帮忙吗?

UPDATE:添加了完整的代码。

错误:无法读取未定义的属性"weight"

所以我在JSON中添加了一些节点,因为我认为d3总是需要一个节点。

只要将新创建的节点数组分配给nodes变量,就应该将其传递给部队布局,而不是links.nodes

force
    .nodes(nodes)
    .links(json.links)
    .start();

或者只需将其添加到links对象

...
json.links.forEach(function(e) { 
    count++;
    nodes.push({name: "test_"+e.source, orientation: e.orientation});
});
links.nodes = nodes;
...

所以我可以找到一种方法:

我的JSON文件:

[
    {"source":"entry","target":"chocolate","value":20,"orientation":"down","x": 200, "y": 150},
    {"source":"chocolate","target":"bread","value":1,"orientation":"left","x": 140, "y": 300},
     {"source":"bread","target":"soap","value":1,"orientation":"right","x": 400, "y": 190}
    ]

我的JS代码:

var width = 960,
    height = 500;
var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);
var force = d3.layout.force()
    .size([width, height])
    .linkDistance(20)
    .charge(-500);
d3.json("name.json", function(error, links) {
  if (error) throw error;
  var nodesByName = {};
  // Create nodes for each unique source and target.
  links.forEach(function(link) {
    link.source = nodeByName(link.source);
    link.target = nodeByName(link.target);
  });
  // Extract the array of nodes from the map by name.
  var nodes = d3.values(nodesByName);
  // Create the link lines.
  var link = svg.selectAll(".link")
      .data(links)
    .enter().append("line")
      .attr("class", "link");
  // Create the node circles.
  var node = svg.selectAll(".node")
      .data(nodes)
    .enter().append("circle")
      .attr("class", "node")
      .attr("r", 4.5)
      .call(force.drag); 
  // Start the force layout.
  force
      .nodes(nodes)
      .links(links)
      .on("tick", tick)
      .start();
  function tick() {
    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; });
    node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
  }
  function nodeByName(name) {
    return nodesByName[name] || (nodesByName[name] = {name: name});
  }
});
});

它可以绘制所需的布局。

  • 参考:https://gist.github.com/mbostock/2949937

谢谢!