javascript - 如何在力导向图中绘制线/边?

标签 javascript d3.js

我正在尝试使用 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);

最佳答案

查看您的links数组:

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

正如您所看到的,无论是对于目标还是对于源,都没有国家作为值。这些链接使用节点的索引

因此,这...

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

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

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

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

关于javascript - 如何在力导向图中绘制线/边?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46963063/

相关文章:

javascript - Slick carousel - 强制幻灯片具有相同的高度

javascript - scaleTime() 上的刻度线不起作用

javascript - 如何获取用户鼠标悬停的圆心的 x,y 坐标?

javascript - 使用不同的值和不同的数据大小更新 D3 柱形图

javascript - 使用 d3.js 将 NUTS 数据渲染到浏览器中的 map

javascript - 仅针对 jquery ui slider 的特定值做一些非凡的事情

javascript - 如何使用 java 脚本将动态值存储在本地存储中?

javascript - 隐藏所有没有深层嵌套特定类的元素

javascript - Owl Carousel 上的重叠幻灯片

javascript - 如何在 ts Angular 2 应用程序中使用纯 js lib