Force directed graph: basics

To create a D3 force directed graph you really only need three things:

  • Nodes
  • A simulation
  • Forces to act on the simulation

There’s also some things that are optional, but real useful:

  • Links
  • Node attributes

Great. Let’s learn more.

Nodes Link to heading

What are nodes? They’re an array of objects.

Nodes can be anything. Here’s three examples:

  • people in a friendship group
  • telegraph poles in a distributed grid
  • articles on a Wikipedia page

Nodes are whatever data objects that you want to visualise. We’ll eventually represent each node with a circle on our basic force directed graph.

Typically you’re interested in how the nodes relate to each other. Perhaps a whole bunch of them are linked and you’d like to explore this. Maybe you’re just curious to see if you can find any patterns in your data.

Whatever your reason, the force directed graph deals with nodes really well. It’s designed for it.

You can define some sample nodes yourself really easily in JavaScript. Here’s an example:

var nodes_data =  [
    {"id": "Travis"},
    {"id": "Rake"},
    {"id": "Diana"},
    {"id": "Rachel"},
    {"id": "Shawn"},
    {"id": "Emerald"}
]

The most common way of defining nodes is to put them in another file and read it in using d3.csv or d3.json . This is the approach taken in this example.

Simulation Link to heading

The simulation controls the movement of nodes.

The simulation is the engine of the force directed graph. It decides when movement starts and stops. It determines the position of each node. It decides how fast each node is travelling.

Inside the simulation there’s a number of variables it keeps track of.

These include the “energy” of the graph at any particular moment in time, referred to as alpha. Alpha starts high and decreases over time, and when alpha goes past a certain number, the graph stops moving.

The simulation also holds where each node is and where they are going. It also tracks the forces that are being applied to each node.

Luckily, understanding the simulation is easy.

The simulation is run in a series of discrete steps called ticks. In each tick the simulation updates its variables, like the position and velocity of its nodes, or its alpha value.

Forces Link to heading

Forces are what drive movement of the graph. You apply forces to the simulation to instruct it how to arrange the nodes.

These forces are highly customisable. That’s what’s so good about them.

Here’s some example forces:

  • A centering force – push all nodes towards the centre of the graph
  • A repelling force – push all nodes away from each other, similar to how charged particles repel each other
  • A collision force – make nodes bounce off each other upon contact like two snooker balls.
  • A link force – pull nodes that are linked towards each other as if there was a spring connecting them
  • A constraining force – keep nodes bound inside a particular area, such as a box
  • A positioning force – pull nodes towards certain points. You could use this to split nodes into several categories
  • A gravity force – pull all nodes towards the bottom of the screen with a force proportional to their size

At the start the simulation has no forces applied to it. This means that if you try running the simulation without adding any forces to it, the nodes will sit there and not move. Then you’ll feel frustrated and question why the stupid thing isn’t working.

Node attributes Link to heading

Each node doesn’t have to contain only a name. You can include other information if you like, which are called node attributes.

Node attributes are really useful. You can use them to customise your graph however you please.

Here’s the nodes_data from earlier with a “sex” attribute:

var nodes_data =  [
    {"id": "Travis", "sex": "M"},
    {"id": "Rake", "sex": "M"},
    {"id": "Diana", "sex": "F"},
    {"id": "Rachel", "sex": "F"},
    {"id": "Shawn", "sex": "M"},
    {"id": "Emerald", "sex": "F"}
]

Node attributes allows us to do fun things, like colour all males in blue and all females in red, or make all male nodes twice the size of the female nodes.

The possibilities are constrained only by your imagination and your sense of style.

Links capture relationships in your data. These could be anything from friendships between people, to cables between poles, to citations between academics.

Links are usually represented by the lines between circles. Here’s an example of some links:

var links_data = [
    {"source": "Travis", "target": "Rake"},
    {"source": "Diana", "target": "Rake"},
    {"source": "Diana", "target": "Rachel"},
    {"source": "Rachel", "target": "Rake"},
    {"source": "Rachel", "target": "Shawn"},
    {"source": "Emerald", "target": "Rachel"}
]

They’re not hard to understand.

Summary Link to heading

You now have the basics down.  Congratulations!

I’ll see you in the next article, where we’ll sink our teeth into a working example.


Hope you found that useful! Click here to view to the rest of the force directed graph series.