Joy Division

The Joy Division album cover has a cool history, and is a beautiful example of data driven art. In this tutorial we’re going to recreate it in a more simplistic form.

We’re going to do this with the javascript canvas. No extra API’s. The only HTML we have on the page is a <canvas> element at 300x300 pixels.

Let’s kick things off with some initial setup. You’re not going to see anything render here, because these are the primary lines to setting up the canvas and context which we use to draw.

1
2
3
4
5
6
7
8
9
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');

var size = window.innerWidth;

canvas.width = size;
canvas.height = size;
 

This gives us access to the context which allows us to draw on the page.

Our initial plan of attack here is to create the lines on the canvas, which will be a string of points. From there, we will start to displace the points randomly to give us the effect we desire.

Let’s get some base variables in here: step, which will be the steps in pixels between our points, and an array called lines, which is going to hold our lines.

9
10
11
var step = 10;
var lines = [];

Now we’ll write a function to prepare our lines. A line will consist of a series of points with x and y properties.

11
12
13
14
15
16
17
18
19
20
21
22
  
// Create the lines
for( var i = step; i <= size - step; i += step) {
    
  var line = [];
  for( var j = step; j <= size - step; j+= step ) {
    var point = {x: j, y: i};
    line.push(point)
  } 
  lines.push(line);
}

Our next step will be to draw these lines. Again, we’ll start simple to get something on the page, and we will expand on it later.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
  
// Do the drawing
for(var i = 0; i < lines.length; i++) {

  context.beginPath();
  context.moveTo(lines[i][0].x, lines[i][0].y)
  
  for( var j = 0; j < lines[i].length; j++) {
    context.lineTo(lines[i][j].x, lines[i][j].y);
  }

  context.stroke();
}

Amazing, we have lines on our canvas! Now, the next job we have is to displace them. We will do that up in our first loop, where we create the points.

17
18
19
  var random = Math.random() * 10;
    var point = {x: j, y: i + random};

Ahh, there we have it. Our lines are now jumping all over the place, just as planned. The next step is to get them to distort in the areas that we want—namely, more distorted towards the center, and less towards the edges. We are going to do this with an absolute function.

17
18
19
20
    var distanceToCenter = Math.abs(j - size / 2);
    var variance = Math.max(size / 2 - 50 - distanceToCenter, 0);
    var random = Math.random() * variance / 2 * -1;

We can see here that we’ve made something a little messy. and that we can see through each line, which doesn’t look great. We’re going to use a fill to cover those up. First we’ll set the fill style.

8
9
10
context.fillStyle = '#f9f9f9';
context.lineWidth = 2;

And then we will add in the fill command after the line is drawn. This covers up the messy lines beneath each layer.

37
38
  context.fill();

We’re getting so close now. The only piece left is to make the lines much less jagged. To do this, we’re going to use quadratic curves, and create control points between each one to create a smooth path. The final quadraticCurveTo is the last joining step.

33
34
35
36
37
38
39
40
  for( var j = 0; j < lines[i].length - 2; j++) {
    var xc = (lines[i][j].x + lines[i][j + 1].x) / 2;
    var yc = (lines[i][j].y + lines[i][j + 1].y) / 2;
    context.quadraticCurveTo(lines[i][j].x, lines[i][j].y, xc, yc);
  }

  context.quadraticCurveTo(lines[i][j].x, lines[i][j].y, lines[i][j + 1].x, lines[i][j + 1].y);

And there we have it! You can mess with the steps, and styles and colors for a bunch of different results. All are exciting!