如何在力导向图中绘制线条/边缘?

时间:2017-10-26 20:16:18

标签: javascript d3.js

Iam尝试使用d3.js为数据集实现强制有向图。我的代码输出节点,作为页面顶部的小点,而边缘无法绘制。如果链接被遗漏在模拟之外,节点是正确绘制,任何关于我可能做错的提示都会有所帮助!

link to codepen

数据集:

{ nodes": [
        { "country": "East Timor", "code": "tl" },
        { "country": "Canada", "code": "ca" },
        { "country": "Turkmenistan", "code": "tm" },
        { "country": "United States of America", "code": "us" },
        { "country": "Lithuania", "code": "lt" },
        { "country": "Cambodia", "code": "kh" },
        { "country": "Ethiopia", "code": "et" },
        { "country": "Swaziland", "code": "sz" },
        ],
"links": [
        { "target": 66, "source": 0 },
        { "target": 3, "source": 1 },
        { "target": 100, "source": 2 },
        { "target": 40, "source": 2 },
        { "target": 125, "source": 2 },
        { "target": 147, "source": 2 },
        { "target": 159, "source": 3 },
        { "target": 18, "source": 3 },
        }


let request = new XMLHttpRequest();
request.addEventListener("load", loaded);

function loaded() {
  const data = JSON.parse(request.responseText);

  var nodes = data.nodes;
  var links = data.links;

  // sets up svg
  var svg = d3.select("svg"),
      width = +svg.attr("width"),
      height = +svg.attr("height");


  // starts simulation
  var simulation = d3
  .forceSimulation()
  .force(
    "link",
    d3.forceLink().id(function(d) {
      return d.country;
    })
  )
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

  // creates lines in graph,
  var link = svg
  .append("g")
  .attr("class", "links")
  .selectAll("line")
  .data(links)
  .enter()
  .append("line");


  var node = svg
  .append("g")
  .attr("class", "nodes")
  .selectAll("circle")
  //pass node data
  .data(nodes)

  .enter()
  .append("circle")
  .attr("r", 5)

  .attr("fill", "red")

  .call(
    d3
    .drag()
    .on("start", dragstarted)
    .on("drag", dragged)
    .on("end", dragended)
  );

  simulation
  // pass nodes,on tick call function ticked
    .nodes(nodes)
    .on("tick", ticked);
  // pass links
  simulation.force("link").links(links);

  function ticked() {
    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 dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
  }
}
request.open(
  "GET",
  "https://www.cs.mun.ca/~h65ped/Public/country%20data%20for%20force%20directed%20graph/countries.json",
  true
);
request.send(null);

1 个答案:

答案 0 :(得分:1)

查看您的links数组:

"links": [
    { "target": 66, "source": 0 },
    { "target": 3, "source": 1 },
    { "target": 100, "source": 2 },
    //etc..

如您所见,目标和来源都没有 country 作为值。链接正在使用节点' 指数代替。

因此,这......

.force("link", d3.forceLink().id(function(d) {
    return d.country;
}));

......错了。只需删除id

即可
.force("link", d3.forceLink());

以下是更新的Codepen:https://codepen.io/anon/pen/NwKvbg?editors=0010