Creating a Book Cover Using JavaScript and p5.js
Tags: p5js, creativecoding, javascript, animation
Published: 2017-05-29 05:39:25

---
title: Creating a Book Cover Using JavaScript and p5.js
published: true
description: A comprehensive introduction to creating visuals using p5.js
tags: p5.js, creative coding, javascript, animation
cover_image: https://thepracticaldev.s3.amazonaws.com/i/6p1pgh0bgmg8q1do74nq.jpg
---

![book-cover](http://i.imgur.com/bippZ2M.gif)

*Note: This Post was originally published on [CSS-Tricks](https://css-tricks.com/creating-book-cover-using-javascript-p5-js/).*

I recently published a book and an interactive course called [Coding for Visual Learners](http://www.codingforvisuallearners.com). It teaches coding to beginners from scratch using the widely popular JavaScript programming language and the p5.js programming library. Since p5.js a great and an easy to use drawing library, I wanted to make use of it to create the cover of my [book](http://i.imgur.com/9EJuFze.jpg) and course as well. This is a tutorial on how to create this particular visual using JavaScript and p5.js.

p5.js is a drawing & creative coding library that is based on the idea of sketching. Just like how sketching can be thought of as a minimal approach to drawing to quickly prototype an idea, p5.js is built on the concept of writing the minimal amount of code to translate your visual, interaction or animation ideas to the screen. p5.js is a JavaScript implementation of the popular library called **Processing** which is based on the **Java** programming language.

The concise nature of p5.js makes it a very easy library to learn. But don’t let this simplicity trick you into believing that p5.js has limited capabilities. p5.js has an impressive amount of functionality, history and community behind it to make it a valuable learning investment if you ever wanted to create art, design, motion or interactive pieces using code. A p5.js program can be anywhere from a few lines of code to thousands.

You can use p5.js to build intricate data visualizations:
<iframe height='500' scrolling='no' title='p5.js data visualization' src='//codepen.io/enginarslan/embed/preview/aJJmZP/?height=650&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/aJJmZP/'>p5.js data visualization</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

or generative art.
<iframe height='500' scrolling='no' title='p5.js generative art' src='//codepen.io/enginarslan/embed/preview/XMMjjP/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/XMMjjP/'>p5.js generative art</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

In this tutorial, I will be assuming a bit of JavaScript knowledge like familiarity with if-else structures, arrays, etc. If you would like to brush up your JavaScript knowledge or would like to learn this powerful language from scratch I would highly recommend you to check out my book and the course [Coding for Visual Learners](http://www.codingforvisuallearners.com). It is tailored for the absolute beginner.

I will also assume some level of familiarity with computer graphics so that concepts like coordinate systems or color modes don't require too much explanation. But in case if anything is not clear, feel free to reach out to me and I will do my best to clarify things.

You can follow along with this write-up either using the [p5.js editor](https://p5js.org/download/) on your operating system or use an online code editor. Here is a [pen](http://codepen.io/enginarslan/pen/xqqEqB) that can serve as a template for your p5.js projects.

Let's get started!

## Part One: p5.js Basics

### setup & draw functions

Most p5.js scripts contain two function declarations called **setup** and **draw**. You will be writing all of your p5.js related code inside these two functions and p5.js will execute these functions for you in particular ways. It is important to understand how these functions are executed by p5.js since they form the backbone of any p5.js program.

**setup** function is where you will be writing code that is related to initialization of your program. Anything that is written inside the **setup** function gets executed once and it gets executed at the beginning of the program.

**draw** function is where you will be writing most of the drawing related functionality. **draw** function gets executed after the **setup** function and it gets executed continuously (close to 60 times, frames, a second by default) which lets you create all kinds of interactive and animated visuals using this library.

Given **draw** and **setup** functions are pretty essential to the workings of p5.js, this is the boilerplate code that you would need to use for almost every p5.js code you write.

<iframe height='500' scrolling='no' title='book-cover-step-01' src='//codepen.io/enginarslan/embed/EWZbmQ/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/EWZbmQ/'>book-cover-step-01</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

If you don't explicitly instruct it, p5.js creates a canvas (the drawing area inside the web page that you will be using) using a default size which is probably too small for your purposes. That's why you are calling the **createCanvas** function which creates a canvas explicitly using the given x and y dimensions. You are also calling the **background** function inside the **draw** function to be able to set a color for the canvas as well. This might not be necessary for boilerplate purposes but it helps with seeing the created canvas.

### Colors & Shapes in p5.js

Color setting functions in p5.js, like the **background** function you are using here, works with either one, two, three or four arguments. A single argument creates a solid color using the given value for the R, G, and B (Red, Green, Blue) components. Calling a color setting function with a single value is same as calling it with the same value as three separate arguments. These two declarations below would create the same result:

```javascript
background(150);
background(150, 150, 150);
```

A fourth argument, when provided, sets the alpha (transparency) for the color. A second argument, when is used as the last argument also controls the alpha of the color and hence the alpha of the shapes that you draw after it. Talking of shapes, let's create a shape. Here is a rectangle, drawn by using the **rect** function.

<iframe height='500' scrolling='no' title='book-cover-step-02' src='//codepen.io/enginarslan/embed/PpWOjY/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/PpWOjY/'>book-cover-step-02</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

First two arguments to the **rect** function set the position of the rectangle and the last two arguments are for setting the size. Notice how when used with the arguments `0` and `0`, the rectangle is drawn to the top-left of the screen. `0, 0` is the origin point for the canvas and it resides at the top-left corner. Rectangle shapes are drawn from their top-left corner by default in p5.js. If you wanted to change this behavior, you can declare a function called **rectMode** with the p5.js variable **CENTER** to change the rectangle drawing mode. It makes sense to place this declaration inside the **setup** function since you will only have to do it once for the lifetime of a program.

<iframe height='500' scrolling='no' title='book-cover-step-03' src='//codepen.io/enginarslan/embed/vxgWZP/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/vxgWZP/'>book-cover-step-03</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

If you wanted to draw this rectangle right in the middle of the screen, you have a couple of options. You could provide it with the value `700/2` so that it would be using half of the width and half of the height. But hard-coding values like this is not a good programming practice. You could try sharing variables among the **rect** function and the **setup** and **draw** functions. But luckily, since placing things relative to the width and height of the canvas is a common operation, p5.js provides you with a shortcut. You can use the p5.js variables **width** and **height** to be able to get the current width and height of the canvas. Divide these variables by two to use them for the placement of the rectangle.

<iframe height='500' scrolling='no' title='book-cover-step-04' src='//codepen.io/enginarslan/embed/VpPrzg/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/VpPrzg/'>book-cover-step-04</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

So far, you know how to set the color for the background but haven't seen how to set the color for the shapes yet. There are two functions that allow you to do so. One of them is the **fill** function that sets the fill color for the shapes that comes after this function declaration and then there is the **stroke** function that sets the color for the stroke.

How color functions work might feel bit unintuitive since they affect the shapes that come after the declaration and not before. To understand how they operate, you can think of calling these functions as setting the active color for the consecutive drawing operations.

Another related function is **strokeWidth**, which sets the width of the stroke of the shapes. You will be using all these three functions to create a transparent rectangle with white borders.

<iframe height='500' scrolling='no' title='book-cover-step-05' src='//codepen.io/enginarslan/embed/GWrOMV/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/GWrOMV/'>book-cover-step-05</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

You will also create a text in the middle of the screen. For this purpose, you will be using the **text** function. **text** function takes 3 inputs, the text to be drawn to the screen and the x and the y position for the text placement. You can also use the **textFont** function to set the desired font for the text.

<iframe height='500' scrolling='no' title='book-cover-step-06' src='//codepen.io/enginarslan/embed/KWayya/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/KWayya/'>book-cover-step-06</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

There are a couple of things to fix here. First of all, notice how the text is not center aligned. As you can guess by now, there is a function to set how text is aligned, called the **textAlign** function. You will be using the **textAlign** function in the **setup** function since you won't be changing this property again. You will provide it with two arguments; `CENTER, CENTER`. This will make the text drawings to be horizontally and vertically aligned.

The second thing to notice is that the text shape is being affected by the fill and stroke values of the rectangle above but you probably don't want to use these values when drawing the text. Let's set new values before drawing the text to get rid of the previous values. 

<iframe height='500' scrolling='no' title='book-cover-step-07' src='//codepen.io/enginarslan/embed/bqgYaE/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/bqgYaE/'>book-cover-step-07</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

To be able to adjust the stroke, you could have either make the stroke color to be transparent or set the strokeWeight to be 0. There is also a **noStroke** function that is used here which gets rid of the stroke altogether. It doesn't really matter which one you choose in my opinion, they all have the same effect in this use case.

You will now adjust the shape of the rectangle to encompass this text a bit better. Also, you will make the background black for legibility purposes.

<iframe height='500' scrolling='no' title='book-cover-step-08' src='//codepen.io/enginarslan/embed/ZeLavX/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/ZeLavX/'>book-cover-step-08</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

Currently, the text and the rectangle is too small. You already know how to scale up the rectangle. To be able to change the size of the text you could be using a function called **textSize**. But you will instead use a p5.js transformation function, **scale**, to handle the scaling since it will allow you to control the scale for the rectangle and the text together in a more straightforward manner. Unfortunately, transformations are not very intuitive when working with p5.js so they require a further explanation.

### p5.js transformation functions

Transformations in p5.js happen relative to the origin point. There is a **scale** function that you can use which would scale the shapes that come after itself by the given amount, but things will get scaled from the origin point; the top-left corner of the screen. This is rarely desirable. When working with shapes, you would generally want to scale them relative to their center point.

Notice how calling the **scale** function makes everything bigger but also displaces them since scaling is happening relative to the top-left corner. 

<iframe height='500' scrolling='no' title='book-cover-step-09' src='//codepen.io/enginarslan/embed/YZNEeM/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/YZNEeM/'>book-cover-step-09</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

If only the shape was at the origin point then this scaling operation would have worked for our purposes. Luckily there is a way to achieve that. For this, you should be using the **scale** function alongside with the **translate** function. Here is how it works:

<iframe height='500' scrolling='no' title='book-cover-step-10' src='//codepen.io/enginarslan/embed/OpWOZV/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/OpWOZV/'>book-cover-step-10</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

You have set the x and y position for both the rectangle and the text to be 0. This moves the shapes to the origin point. Then you call the **translate** transformation function to move the shapes to their initial position at `width/2` and `height/2`. This works because **translate** function actually doesn't move the shapes, it moves the entire coordinate system. Now that the origin of the coordinate system is in the middle of the screen, you can call the **scale** function, which would do the scaling from this desired point. 

Now if this sounds a bit convoluted to you, let me assure that you are not alone. Moving the entire coordinate system to transform a shape is not only an overkill for what you are trying to achieve but can also be impractical since it means that anything else that comes after these shapes will need to use this newly transformed coordinate system which adds a lot of complexity to the process. Let's see it in an example by drawing a new shape.

<iframe height='500' scrolling='no' title='book-cover-step-10-B' src='//codepen.io/enginarslan/embed/ryyMdo/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/ryyMdo/'>book-cover-step-10-B</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

As you can see, you are now drawing a circle using the ellipse function at the x and y coordinates of 120 and 0. But the problem is that even though the provided y value is at 0, you can clearly see that the circle is not at top of the screen but in the middle, which happens to be the new 0 value for the y-axis. This would be highly undesirable for most circumstances but luckily there is a way in p5.js to deal with it. Enter the **push** and **pop** functions!

### push & pop

The p5.js **push** function allows you to create a new state and **pop** function restores the state to the previous conditions. This allows you to have completely different settings applied to individual objects without worrying those settings to affect the shapes that come after as long as you do everything in between a **push** and a **pop** call. Here is how it works:

<iframe height='500' scrolling='no' title='book-cover-step-11' src='//codepen.io/enginarslan/embed/evgery/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/evgery/'>book-cover-step-11</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

Perfect! All that transformation changes you are doing right now remains localized in between the **push** and **pop** function calls. It is important to note that you should always call **push** and **pop** functions together. Using one but not the other doesn't make any sense. Now that you fixed the problems regarding transformations, you can get rid of the circle shape. One final thing you will be adding before finalizing this text on the screen is to add a bit of an animation to it. Let's scale it up a little bit for the first 200 frames of the animation to add a bit more dynamism to the visual. For this purpose, you can use the **frameCount** p5.js variable. **frameCount** p5.js variable keeps track of the number of times the **draw** function is called during the lifetime of a p5.js program.

<iframe height='500' scrolling='no' title='book-cover-step-12' src='//codepen.io/enginarslan/embed/GWrOBR/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/GWrOBR/'>book-cover-step-12</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

The following code snippet is added to the program. If the **frameCount** is less than 200 it adds `1/400` of the current **frameCount** value to the current scale. The reason why you are using the number 400 is that when the frameCount is 200 you would like to have 0.5 added to the total scale. But this is not the most elegant or scalable way of tackling this problem.

```javascript
if (frameCount < 200) {
    scale(1.5 + frameCount/400);
} else {
    scale(2);
}
```

One p5.js function that you can use to derive this incremental scaling value is the **map** function. **map** function maps the given value that is expected to be in between the given minimum and maximum range to a number in the desired minimum and maximum range. The following declaration:

```javascript
map(frameCount, 0, 200, 0, 0.5);
```

will map the **frameCount** variable that is in between 0 and 200 to a value in between 0 and 0.5. Let's make use of it inside the code:

<iframe height='500' scrolling='no' title='book-cover-step-13' src='//codepen.io/enginarslan/embed/JWEOee/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/JWEOee/'>book-cover-step-13</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>


This is so much better. And the code is very scalable as well. You could just be changing the **scaleFactor** and **maxLimit** variables to adjust how much and how fast the text grows. In the next part of this walkthrough, you will be building the background effect of the final visual, which is arguably the more exciting part of this visual. But the parts you have seen so far should be enough to get you familiarized with the basics of p5.js.

## Part Two: Creating the Ring Shapes

In this second part of the tutorial, you will learn about creating the animated, ring-like shapes in the background. But first, let's move the text drawing code to its own function so that it doesn't occupy so much space inside the **draw** function.

<iframe height='500' scrolling='no' title='book-cover-step-14' src='//codepen.io/enginarslan/embed/Nppraq/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/Nppraq/'>book-cover-step-14</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

This update didn't introduce any functionality change but is only a structural update to the code to make it more legible. You won't need the **drawTitleText** function for now, so you can comment it out to be able to focus on the background shapes. 

You will use a JavaScript object to represent the numbers for the final visual on the screen. Using an object to create as shape makes it easier to think about the shape as an entity of its own with a certain set of properties and behaviors. It also helps with encapsulating the functionality that is relevant to the shape, under the shape itself, which is good for code organization.

Here, you are creating a JavaScript constructor function called `Num` to represent the numbers that are used in the ring. It takes a couple of arguments; a message for the shape to display, the x, y position, the rotation and the color values for the shape. You haven't seen the **rotate** function before but it is pretty similar to **scale** or **translate** functions. As the name implies, it transforms the shape by rotating it.

```javascript
function Num(msg, x, y, rot, clr) {
    this.x = x;
    this.y = y;
    this.rot = rot;
    this.msg = msg;
    this.color = clr;

    this.render = function() {
        push();
        fill(this.color);
        translate(this.x, this.y);
        rotate(this.rot);
        text(this.msg, 0, 0);
        pop();
    }
}
```

The constructor function has a **render** method that handles the drawing of the shape to the screen. You can now use this constructor function to initialize an instance of this shape object and draw it on the screen.

<iframe height='500' scrolling='no' title='book-cover-step-15' src='//codepen.io/enginarslan/embed/aJJZqq/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/aJJZqq/'>book-cover-step-15</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

A Couple of things that are worth mentioning.

First of all, notice how the `Num` function is pretty generic. It could be used to render any text to the screen in a flexible manner. It is also easy to use since you can simply control the rotation by defining the desired rotation value instead of using **push** and **pop** functions externally.

Secondly, see how certain words are being avoided when declaring functions. You could have called the constructor function `Number` instead of `Num` but `Number` is an already existing function in JavaScript so you should try to avoid it. Things wouldn't necessarily explode if you were to use `Number` but it is generally a good idea to not cause name conflicts. Also for the arguments, you are not using the `rotate` or `color` as parameter names as these are the names for built-in p5.js functions. If you are to use these names for arguments then you would not be able to use the functions that are using the same name in the context of this function. Learning how to avoid these names comes with practice.

Finally, notice how you are providing a rotation value of 90 to the number object, but the number doesn't seem to have rotated 90 degrees. That's because p5.js uses _radians_ by default when performing rotations instead of _degrees_. You can set it to use degrees as the default rotation unit by calling the p5.js **angleMode** function with the **DEGREES** variable inside the **setup** function.

```javascript
angleMode(DEGREES);
```

It is great that there is now a single number on the screen but the aim is to have several numbers in a ring formation. Let's figure out how to do this for a single number and then you can scale the operation to do placement for an arbitrary amount of numbers.

<iframe height='500' scrolling='no' title='book-cover-step-16' src='//codepen.io/enginarslan/embed/QppErE/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/QppErE/'>book-cover-step-16</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

The code is growing in size! This is the code that is added for creating the ring layout. 

```javascript
var radius = 100;
var amount = 15;

push();
translate(width / 2, height / 2);

for (var i = 0; i < amount; i++) {
    rotate(i);
    var num = new Num(1, 0 + radius, 0, 90, 255);
    num.render();
}

pop();
```

Here we have a for-loop that creates a given amount of **Num** objects that are away from the current origin, by the given **radius** amount. This is currently only creating 15 objects. This is to illustrate a point. See how the spacing around the shapes is not even. This happens because transformation calls in p5.js (like **translate**, **rotate**, **scale**) have a cumulative effect. For example, these two calls that are listed below would result in a total translation of 20 pixels in the x-axis. 

```javascript
translate(10, 0);
translate(10, 0);
```

To remedy this you can use the **push** and **pop** so that the transformation effects remain localized and don't accumulate. That should take care of the uneven spacing of shapes. You should also make it so that the shapes are evenly distributed around the imaginary circle. To do this you can just divide 360 (the total angle of a circle) with the number of shapes you have to derive how much you should rotate each shape to achieve an even distribution.

<iframe height='500' scrolling='no' title='book-cover-step-17' src='//codepen.io/enginarslan/embed/RppRJO/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/RppRJO/'>book-cover-step-17</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

Perfect, in the next step, you will be creating a function out of this ring drawing operation. You will make the function to accept **radius** and **amount** as arguments. Also inside the function, you will be generating an array of random numbers to be fed into the **Num** object so that you can pass a random value of 0 or 1 to the object, instead of always using number 1.

For this purpose, you will use the p5.js **random** function. Here is a snippet that generates a random floating point number in between 0 and 2 (excluding 2) that gets converted to an integer using the JavaScript **parseInt** function and gets pushed into an array.

```javascript
var randomNumbers = [];
for (var i = 0; i <= amount; i++) {
    randomNumbers.push(parseInt(random(2), 10));
}
```

Now you can pass an item from this **randomNumbers** collection to the **Num** object instead of always using the number 1. Here is the entire code:

<iframe height='500' scrolling='no' title='book-cover-step-18' src='//codepen.io/enginarslan/embed/MppeBo/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/MppeBo/'>book-cover-step-18</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

The problem right now is that the p5.js **random** function is generating a random value for each **draw** function call but for our purposes, we would like these random values to remain the same throughout the execution of the program. To be able to do so you should use the p5.js **randomSeed** function. The **randomSeed** makes sure you are getting the same "random" values for the given seed value. You will make it so that the seed should be configurable from outside the function.

<iframe height='500' scrolling='no' title='book-cover-step-19' src='//codepen.io/enginarslan/embed/JWWKVm/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/JWWKVm/'>book-cover-step-19</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

The numbers are not flickering anymore. Since you created the function that draws a single ring, it is not hard at all at this point to draw multiple rings with varying amounts of **Num** objects using a loop. To keep the example simple, we are using a numeric constant to keep the density of the rings similar to each other.

<iframe height='500' scrolling='no' title='book-cover-step-19-B' src='//codepen.io/enginarslan/embed/gmmwqW/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/gmmwqW/'>book-cover-step-19-B</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

You are almost done! In fact, I am going to just show the final code at this point, as it doesn't contain anything you haven't learned about. 

Here are a couple of things that are updated in this version.
- Updated the background for the Coding for Visual Learners Text so that it's semi-transparent.
- Introduced rotation to the rings.
- Introduced randomness to the color of the Num objects as well.

<iframe height='500' scrolling='no' title='Coding for Visual Learners - Cover' src='//codepen.io/enginarslan/embed/preview/WppxBo/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/enginarslan/pen/WppxBo/'>Coding for Visual Learners - Cover</a> by Engin Arslan (<a href='https://codepen.io/enginarslan'>@enginarslan</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>

In case you didn't want the shape to be animated, you can just call a function called **noLoop** inside the **setup** function to only display the first frame of the animation. If you wanted to adjust the shape you can start off by tweaking the **amount**, **spacing**, **radius** and **rotSpeed** parameters.

I used the static image for my book cover but the animated shape to create animations for the course. To be fair, I also used Photoshop a bit for the placement of some of the elements but the base shape is created with JavaScript and p5.js which makes me happy as a programmer.

I hope you enjoyed this short introduction to p5.js! Feel free to reach out to me if you have any questions! You can find my website at [enginarslan.com](http://enginarslan.com/) and I am on Twitter at [@inspiratory](https://twitter.com/inspiratory). You can find more about my book/online course [here](http://www.codingforvisuallearners.com/).