Reputation: 230
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?
Upvotes: 1
Views: 1818
Reputation: 21578
There are two errors in the code you posted in your question:
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)
.
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