I have a force graph with colored nodes that I am trying to add labels to. Right now it has labels, but it\'s the small, hard to read ones native to the browser. How would I
There is a confusion between "labels" and "tooltips". Traditionally, we name "labels" the texts that show up next to the nodes without user interaction, and we name "tooltips" the texts that show up when the user interacts with the nodes (for instance, hovering the nodes).
So, if you mean "labels", this is a solution: append the nodes as groups...
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.call(d3.drag().on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
And append the circles and the labels (as <text>
elements) to them:
node.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); });
node.append("text")
.attr("dx", 6)
.text(function(d) { return d.id; });
Here is a demo using (most of) your code, with a made up data:
var graph = {
nodes:[
{"id": "A", "group": 1},
{"id": "B", "group": 2},
{"id": "C", "group": 2},
{"id": "D", "group": 2},
{"id": "E", "group": 2},
{"id": "F", "group": 3},
{"id": "G", "group": 3},
{"id": "H", "group": 3},
{"id": "I", "group": 3}
],
links:[
{"source": "A", "target": "B", "value": 1},
{"source": "B", "target": "C", "value": 1},
{"source": "A", "target": "D", "value": 1},
{"source": "H", "target": "E", "value": 1},
{"source": "I", "target": "F", "value": 1},
{"source": "A", "target": "G", "value": 1},
{"source": "B", "target": "H", "value": 1},
{"source": "A", "target": "I", "value": 1},
]
};
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; }).distance(40))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
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.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
node.append("circle")
.attr("r", 5)
.attr("fill", function(d) { return color(d.group); });
node.append("text")
.attr("dx", 6)
.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("transform", function(d) {
return "translate(" + d.x + "," + 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;
}
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.node circle {
stroke: #fff;
stroke-width: 1.5px;
}
.node text{
fill: #666;
font-family: Helvetica
}
<svg width="400" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>