D3.js Force Layout — Network Graphs and Node Layout
In this tutorial, you will learn about D3.js Force Layout. We cover key concepts, practical examples, and best practices to help you master this topic.
D3.js force layout positions nodes in a network graph by simulating physical forces such as attraction, repulsion, and collision for interactive node-link diagrams.
What You'll Learn
By the end of this guide, you will create a force simulation, add nodes with links, configure charge, link, and collision forces, implement drag behavior, color-code node groups, and animate the simulation.
Why Force Layout Matters
Network visualization reveals relationships. Durga Antivirus Pro uses force layout to map malware propagation paths, showing how an infection spreads from node to node across a network.
flowchart LR
A[Node Data] --> B[Force Simulation]
C[Link Data] --> B
B --> D[Charge Force - Repulsion]
B --> E[Link Force - Attraction]
B --> F[Center Force - Gravity]
B --> G[Collision Force]
D --> H[Animated SVG]
E --> H
F --> H
G --> H
Basic Force Simulation
var nodes = [
{ id: 'A' }, { id: 'B' }, { id: 'C' },
{ id: 'D' }, { id: 'E' }
];
var links = [
{ source: 'A', target: 'B' },
{ source: 'A', target: 'C' },
{ source: 'B', target: 'D' },
{ source: 'C', target: 'E' },
{ source: 'D', target: 'E' }
];
var simulation = d3.forceSimulation(nodes)
.force('link', d3.forceLink(links).id(function(d) { return d.id; }))
.force('charge', d3.forceManyBody().strength(-100))
.force('center', d3.forceCenter(300, 200));
Rendering the Graph
var svg = d3.select('#graph')
.append('svg')
.attr('width', 600)
.attr('height', 400);
var link = svg.append('g')
.selectAll('line')
.data(links)
.enter()
.append('line')
.attr('stroke', '#999')
.attr('stroke-width', 2);
var node = svg.append('g')
.selectAll('circle')
.data(nodes)
.enter()
.append('circle')
.attr('r', 8)
.attr('fill', '#4ecdc4');
node.append('title')
.text(function(d) { return d.id; });
simulation.on('tick', function() {
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; });
});
Expected output: 5 circles connected by lines, automatically positioning themselves with physics-based layout.
Dragging Nodes
var drag = d3.drag()
.on('start', function(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
})
.on('drag', function(event, d) {
d.fx = event.x;
d.fy = event.y;
})
.on('end', function(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
});
node.call(drag);
Configuring Forces
simulation
.force('link', d3.forceLink(links)
.id(function(d) { return d.id; })
.distance(100)
.strength(0.5)
)
.force('charge', d3.forceManyBody()
.strength(-200)
.distanceMin(20)
.distanceMax(500)
)
.force('center', d3.forceCenter(300, 200))
.force('collision', d3.forceCollide(15));
Common Mistakes
1. Not Calling simulation.on('tick')
Without the tick handler, nodes and links never update their positions.
2. Mixing Up source and target in Links
Link source and target must reference node IDs or indices. Wrong references cause NaN positions.
3. Infinite Simulation
The simulation stops when alpha reaches 0. For continuous interaction, restart with .alphaTarget(0.3).
4. Nodes Overlapping
Add d3.forceCollide(radius) to prevent nodes from overlapping visually.
5. No Id Accessor for Links
Links need an id accessor to match string IDs to node objects. Without it, links fail silently.
Practice Questions
Q1: What forces are commonly used in force simulation? A: Link (connects nodes), charge (repulsion/attraction), center (gravity toward center), and collision (prevents overlap).
Q2: What does the tick event do? A: It fires on every simulation step (typically 60fps), allowing you to update node and link positions in the SVG.
Q3: How do you make nodes draggable?
A: Call .call(d3.drag()) on the node selection and handle start, drag, and end events.
Q4: What is alpha in the simulation? A: Alpha is the simulation's energy level. Higher values cause more movement. It decays to 0 as the simulation stabilizes.
Q5: How do you restart a stopped simulation?
A: Call simulation.alpha(0.3).restart() to inject energy and resume.
Challenge: Build a network graph representing a social network with 20 nodes and 30 links. Color nodes by community (use groups). Allow dragging. Show node names on hover.
FAQ
Try It Yourself
Build an interactive network graph with drag, hover labels, and color-coded groups.
<!DOCTYPE html>
<html>
<head>
<title>Force Layout Demo</title>
<style>
body { font-family: sans-serif; padding: 20px; background: #1a1a2e; }
svg { background: #16213e; border-radius: 12px; display: block; margin: auto; }
.link { stroke: #555; stroke-opacity: 0.6; }
.node { stroke: #fff; stroke-width: 2; cursor: grab; }
.label { fill: #ccc; font-size: 11px; pointer-events: none; }
</style>
</head>
<body>
<svg width="700" height="500" id="graph"></svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
var nodes = d3.range(15).map(function(i) {
return { id: 'Node ' + i, group: i % 3 };
});
var links = [];
for (var i = 0; i < 15; i++) {
for (var j = i + 1; j < 15; j++) {
if (Math.random() < 0.15) {
links.push({ source: i, target: j });
}
}
}
var svg = d3.select('#graph');
var width = +svg.attr('width');
var height = +svg.attr('height');
var colors = ['#ff6b35', '#4ecdc4', '#45b7d1'];
var link = svg.append('g')
.selectAll('line').data(links).enter()
.append('line').attr('class', 'link');
var node = svg.append('g')
.selectAll('circle').data(nodes).enter()
.append('circle')
.attr('class', 'node')
.attr('r', 10)
.attr('fill', function(d) { return colors[d.group]; });
var labels = svg.append('g')
.selectAll('text').data(nodes).enter()
.append('text')
.attr('class', 'label')
.text(function(d) { return d.id; });
var sim = d3.forceSimulation(nodes)
.force('link', d3.forceLink(links).distance(80))
.force('charge', d3.forceManyBody().strength(-120))
.force('center', d3.forceCenter(width/2, height/2))
.force('collision', d3.forceCollide(15));
sim.on('tick', function() {
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; });
labels.attr('x', function(d) { return d.x + 14; }).attr('y', function(d) { return d.y + 4; });
});
var drag = d3.drag()
.on('start', function(e, d) { if (!e.active) sim.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; })
.on('drag', function(e, d) { d.fx = e.x; d.fy = e.y; })
.on('end', function(e, d) { if (!e.active) sim.alphaTarget(0); d.fx = null; d.fy = null; });
node.call(drag);
</script>
</body>
</html>
What's Next
Visualize hierarchical data with tree layouts.
Hierarchies — Tree and cluster layouts. Geo Maps — Geographic map visualization.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro