Author avatar

Benney Au

Creating Force Layout Graphs in D3

Benney Au

  • Sep 24, 2020
  • 5 Min read
  • 79 Views
  • Sep 24, 2020
  • 5 Min read
  • 79 Views
IT Infrastructure
Container Management
Docker
Containers

Introduction

Force layout graphs are a useful tool for understanding large amounts of data, and the relationships between data points within the data. This type of graph consists of elements represented by squares or circles, and the data is arranged by simulating forces pushing and pulling on them. This allows users to easily see the relationships between elements and the most significant element within the dataset.

This guide will demonstrate how to use the d3-force package to create force layout graphs. The guide assumes you have basic understanding of D3.js.

Understanding the Components of d3-force

The unique aspect of force layout charts is the ability to simulate pushing and pulling of nodes within geometric constraints, or forces. Forces are functions that allow you to control the size and position of nodes in relation to each other and the simulation. There are, broadly, five categories of forces in d3-force:

  • Centering: Translates nodes so their mean position is at position x, y. This force is useful for centering the nodes within a viewport rather than bunching them up in a corner.
  • Collision: Treats nodes as circles with a radius and helps prevent them from overlapping each other
  • Links: Push linked nodes together or apart based on link distance. This is useful for representing the strength of a relationship between nodes.
  • Many-Body: Pushes all nodes further apart or pulls all nodes closer together. By convention, a positive many-body force that pushes nodes further apart is named charge and a negative force that pulls nodes closer together is named gravity.

Create a Simple Force Layout Graph

One way to easily get started experimenting with d3-force is using Observable HQ. This website offers an interactive editing experience that doesn't require you to install anything.

Start by forking this simple force layout observable HQ sample. This sample is based on code and data from Daniel Stern's GitHub Repository.

The first section of code imports D3.js and some sample data required to bind to force layout chart. The main part of the chart code is listed below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
  const simulation = d3.forceSimulation(data.nodes)
   .force('charge', d3.forceManyBody().strength(-100))
   .force('link', d3.forceLink(data.links).id(d => d.id)
         .distance(50))
    .force('center', d3.forceCenter(300, 300))
  
    const svg = d3.create("svg").attr("viewBox", [0, 0
                        , 600, 600]);
  
   const node = svg.selectAll('circle')
     .data(data.nodes)
     .enter()
     .append('circle')
     .attr('r', 25)
     .attr('fill', 'blue');
  
   const link = svg
     .selectAll('path.link')
     .data(data.links)
     .enter()
     .append('path')
     .attr('stroke', 'black')
     .attr('fill', 'none');
  
  const lineGenerator = d3.line();
   
   simulation.on('tick', () => {
                 node.attr('cx', d => d.x);
                 node.attr('cy', d => d.y);
                 link.attr('d', d => lineGenerator([
                   [d.source.x, d.source.y], 
                   [d.target.x, d.target.y]]) 
                 )
   });
   return svg.node();
}
javascript

The input data has two nodes, and these two nodes have three forces that act upon them:

  • A charge force is a many-body force that pushes nodes further apart from each other. It is called "charge" because it represents a physical electrical charge that creates repulsion between nodes.
  • A link force illustrates direct links between nodes. This force can read the input data to alter the distance between nodes.
  • A center force pushes nodes to the middle of the viewport. Without this force, nodes would be bunched up on the corner.

Finally, the simulation.on('tick', callback) function is called to tell D3.js how to position your nodes and links after each simulation tick. The rest of the code snippet is standard D3.js code and won't be discussed in this guide for brevity.

Update the Force Values

In the previous section you have created a simple force layout chart with a few forces applied. Now you can experiment by changing the values of each force to get the desired effect.

Changing the strength of the charge force influences how much repulsion occurs between all nodes. A greater negative number pushes nodes further apart. A positive strength number pulls nodes closer together.

The center force accepts an x and y position. You can change them to something like [200, 100] to move the center of the mass of nodes closer to the top.

Conclusion

Force layout charts are extremely useful when you have a large amount of data and want to understand some insights about it. You can build on this knowledge by looking at more sophisticated force layout graphs on Observable HQ.

0