Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Last active October 8, 2017 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HarryStevens/2d8d15a34c637cba6a85c6eb039ce072 to your computer and use it in GitHub Desktop.
Save HarryStevens/2d8d15a34c637cba6a85c6eb039ce072 to your computer and use it in GitHub Desktop.
Five Forces
license: gpl-3.0

In a D3.js force layout, you can apply distinct forces to nodes based on attributes of the underlying data. Suppose you want to create six "buckets" of nodes. You can think of each bucket as being placed in one cell of a 2x3 grid:

The letters a through f represent the six options of the underlying data by which we will group our nodes. The columns are labeled x1, x2 and x3 and the rows, y1 and y2. Each of these labels can also be thought of as a distinct force. The x1 force, for example, will apply to groups a and d, dragging their horizontal center to the left side of the screen. The y2 force will apply to groups d, e and f and will drag their vertical center to the bottom half of the screen. And so on.

In a D3 force simulation, you can name your forces whatever you want. I have named my five forces according to the labels:

.force("y1", isolate(d3.forceY(-height / 8), function(d){ return d.class == "a" || d.class == "b" || d.class == "c"; })) // applies to a, b & c
.force("y2", isolate(d3.forceY(height / 8), function(d){ return d.class == "d" || d.class == "e" || d.class == "f"; })) // applies to d, e & f
.force("x1", isolate(d3.forceX(-width / 6), function(d) { return d.class === "a" || d.class == "d"; })) // applies to a & d
.force("x2", isolate(d3.forceX(), function(d) { return d.class === "b" || d.class == "e"; })) // applies to b & e
.force("x3", isolate(d3.forceX(width / 6), function(d) { return d.class === "c" || d.class == "f"; })) // applies to c & f

The isolate() function was taken from this block by Mike Bostock. It can also be seen in action in this block by Manas Sharma (who, incidentally, helped me understand how to do this). Both of those blocks use Canvas rather than SVG, which is necessary if you have a lot of nodes. The drawback to that is that Canvas is a pain to use, particularly if you want to add interactivity like tooltips to your nodes. If you have fewer than 1,000 nodes, you should be okay with SVG – after that, your browser will start to suffer.

This file has been truncated, but you can view the full file.
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/jeezy@1.11.2/lib/jeezy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment