D3 Network Graph Node Labels and Images

Many paths to take…

D3 is an amazing data visualization library that can be used to make any number of interactive data applications. I was recently working with the network graph, which is a visualization of nodes connected by lines to other nodes. The nodes can be dragged around and moved and you can specify parameters during the simulation configuration to get an outcome you want visually.

Using the standard network graph example offered by D3, the nodes are simply colored and linked. It is very helpful to add other properties to the nodes so they become more useful to an end-user. This post will cover how to add text, images, and a little collapsible functionality to the nodes.

Append Text To A Node

Looking at the D3 network graph example above, the nodes have a title if you hover over them:

D3 network graph
Hi Brujon!

But it would be nice if we could just see the node names on each node! Take this code and replace the code on the network graph page, wholesale, and click button in the upper-right:

chart = {
const links = data.links.map(d => Object.create(d));
const nodes = data.nodes.map(d => Object.create(d));
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
const link = svg.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.join("line")
.attr("stroke-width", d => Math.sqrt(d.value));
const node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 1.5)
.selectAll("g")
.data(nodes)
.join("g")
.call(drag(simulation));
node.append("circle")
.attr("stroke", "white")
.attr("stroke-width", 1.5)
.attr("r", 5)
.attr("fill", color);
node.append("text")
.attr("x", 8)
.attr("y", "0.31em")
.attr("stroke", "green")
.text(d => d.id);
simulation.on("tick", () => {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node.attr("transform", d => `translate(${d.x},${d.y})`);
});
invalidation.then(() => simulation.stop());
return svg.node();
}
You can run D3 simulations with tweaks with this framework. Very handy!

Now, when you press play:

D3 network graph nodes with text
A node by any other name…

Not bad! Using the attributes on the node.append(‘text’) section of our code, we can move the text placing around and change the color and size:

node.append("text")
.attr("x", 8)
.attr("y", 0)
.attr("stroke", "blue")
.attr("font-weight", 100)
.attr("font-size", '9px')
.text(d => d.id);
D3 network graph nodes with text 2

Using the same pattern, you can now adjust anything you want about the labels using normal CSS techniques.

Append Image To A Node

Appending an image is done in the same vein as appending text. Use the following code snippet in place, or in conjunction with, the text code above to add an image:

            nodeEnter.append("image")
            .attr("x", -40)
            .attr("y", -40)
            .attr("alt","test")
            .attr("height", 30)
            .attr("width", 30)
            .attr("xlink:href", "https://www.pngitem.com/pimgs/m/55-559996_heart-icon-png-image-hollow-heart-transparent-png.png");

The above link is pointing to a heart icon. When we press play:

D3 network graph odes with text and images

Pretty cool, right!? With this structure, you can do whatever you want with the nodes that are available to you in a force network graph. Try putting your D3 graph in a Salesforce web component and play around with some real data!

Leave a Reply

%d bloggers like this: