力导向图中缺少链接

时间:2017-07-28 18:59:45

标签: d3.js

我使用Modifying a Force Directed Graph II作为图表的基础。我以为我已经处理了我们处理链接格式化的不同方式(Bostock使用引用,我使用字符串),通过更改

simulation.force("link", d3.forceLink(links).distance(200))

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

但没有骰子。链接仍然没有被绘制。我还缺少什么?

My jsfiddle is here.

1 个答案:

答案 0 :(得分:3)

您在问题中发布的代码中有两个错误:

  1. 修改代码中的链接强制时,您不再提供强制链接,因为您没有提供links作为参数。它必须是d3.forceLink(links)

  2. 提供给.id()的函数是节点ID的访问函数。在您的情况下,节点的id由其属性name定义。因此,您需要将访问者更改为.id(function(d) { return d.name; })

  3. 将链接力的定义更改为以下内容以使其起作用:

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

    请查看以下代码片段以了解正常工作:

    nodes = [{
      name: "test",
      type: "test"
    }, {
      name: "test2",
      type: "test2"
    }];
    links = [{
      source: "test",
      target: "test2"
    }];
    
    var width = 500,
      height = 500;
    
    var svg = d3.select("svg"),
      color = "blue";
    
    var simulation = d3.forceSimulation(nodes)
      .force("charge", d3.forceManyBody().strength(-1000))
      .force("link", d3.forceLink(links).id(function(d) {
        return d.name;
      }))
      .force("x", d3.forceX())
      .force("y", d3.forceY());
    
    var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
      link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link"),
      node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");
    
    forceGraphUpdate = function() {
    
      node = node.data(nodes);
      node.exit().transition().attr("r", 0)
        .remove();
    
      node = node.enter().append("circle")
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended))
        .attr("fill", function(d) {
          return color;
        })
        .call(function(node) {
          node.transition().attr("r", 8)
        })
        .merge(node);
    
      link = link.data(links);
    
      link.exit().transition()
        .attr("stroke-opacity", 0)
        .attrTween("x1", function(d) {
          return function() {
            return d.source.x;
          };
        })
        .attrTween("x2", function(d) {
          return function() {
            return d.target.x;
          };
        })
        .attrTween("y1", function(d) {
          return function() {
            return d.source.y;
          };
        })
        .attrTween("y2", function(d) {
          return function() {
            return d.target.y;
          };
        })
        .remove();
    
      link = link.enter().append("line")
        .call(function(link) {
          link.transition().attr("stroke-opacity", 1);
        })
        .merge(link);
    
      simulation
          .nodes(nodes)
          .on("tick", ticked);
     
    }
    
    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;
        });
    }
    
    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;
    }
    
    forceGraphUpdate();
    
    function addNode() {
      nodes.push({
        name: "test",
        type: "testing"
      });
      forceGraphUpdate();
    }
    addNode();
    <script src="https://d3js.org/d3.v4.js"></script>
    <svg width="500" height="500"></svg>