Reputation: 414
I am following this tutorial to create a node-like data visualization.
<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("miserables.json", function(error, graph) {
if (error) throw error;
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); });
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("span")
.text(function(d) { return d.id; });
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.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;
}
</script>
However, I want to text next to each circle with its id/name on it with the extra element g
but nothing is showing up for some reason.
When I inspect each circle. It shows the with the correct id, but the spans are not showing on the graph at all. <circle><span>example id</span></circle>
Upvotes: 1
Views: 891
Reputation: 38211
You are not appending text to g
elements, you are appending text to circles, let's follow your code to see what the variable node
holds:
var node = svg.append("g") // returns a selection holding a g
.attr("class", "nodes") // returns the same g, now with class "nodes"
.selectAll("circle") // returns an empty selection as there are no circles yet
.data(graph.nodes) // returns the empty selection with bound data
.enter().append("circle") // returns a selection of newly entered circles
.attr("r", 5) // continues to return the circles
...
So node
holds a selection of circles, so when using node.append("span")
we are attempting to add text to circles, which won't work. So we need to modify this slightly by breaking up your chaining:
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter().append("g"); // returns a selection of newly entered g elements
node.append("circle") // returns a selection of circles, newly append to each g in node
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
And now since node holds a selection of g elements, we can append text as well:
node.append("text") // returns a selection of text, newly append to each g in node
.text(function(d) { return d.id; });
There is a change here as well, I've changed node.append("span") to node.append("text"), we are appending svg elements, not html elements to the svg. While the span tags may be appended, it won't display as they aren't svg elements.
Lastly, as in this answer, you need to update the translate of each g
in each tick rather than the cx
and cy
properties because a g
isn't positioned by cx and cy attributes:
node
.attr("transform",function(d) { return "translate("+[d.x,d.y]+")"; });
Here's an demo.
Note, to see your links you need to set a stroke color: .attr("stroke","black');
on your lines
Upvotes: 1