Emily Coleman
Emily Coleman

Reputation: 230

Missing links in force directed graph

I'm using Modifying a Force Directed Graph II as a base for my graph. I thought I'd coped with the different ways we're handling how links are formatted (Bostock's uses references, mine uses strings), by changing

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

to

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

but no dice. The links still aren't being drawn. What else am I missing?

My jsfiddle is here.

Upvotes: 1

Views: 1818

Answers (1)

altocumulus
altocumulus

Reputation: 21578

There are two errors in the code you posted in your question:

  1. When modifying the link force in your code you are no longer providing the links to the force since you are not providing links as an argument. It has to be d3.forceLink(links).

  2. The function provided to .id() is the accessor function to the nodes' ids. In your case the id of a node is defined by its property name. Thus, you need to change the accessor to .id(function(d) { return d.name; }).

Change the definition of the link force to the following to make it work:

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

Have a look at the following snippet for a working demo:

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>

Upvotes: 6

Related Questions