Getting Started with p5.js
Learn the fundamentals of creative coding with p5.js.
p5.js is a wonderful JavaScript library that makes creating code-based art on the web easy and fun. It’s perfect for artists, designers, educators, and beginners who want to start creative coding.
What is p5.js?
p5.js is a JavaScript library that started as a reinterpretation of Processing for the web. It simplifies the process of drawing and animation in the browser, making it easier to create visual sketches without stressing over the complex details of rendering.
The library provides a full set of drawing functionality, but is not limited to just drawing. You can use all the capabilities of modern web browsers: HTML5 canvas drawing, audio, video, webcam, and more.
Setting Up Your First p5.js Sketch
There are two main ways to use p5.js: through the online editor or by including it in your own HTML file.
Using the p5.js Web Editor
The easiest way to get started is using the p5.js Web Editor. It’s free, works in your browser, and provides everything you need to create p5.js sketches without installing anything.
It’s great if you just want to get started without getting overwhelmed by setup and tooling
Setting Up p5.js Locally
If you prefer working locally, create an HTML file with the following structure:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My p5.js Sketch</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.1/p5.js"></script>
<!-- If you need sound functionality -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.1/addons/p5.sound.min.js"></script>
<script src="sketch.js"></script>
<style>
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
</style>
</head>
<body>
<!-- Your sketch will be added here automatically -->
</body>
</html>
Then create a sketch.js
file in the same directory with your p5.js code.
The key detail here is the two <script>
tags we put in the head of the HTML. The first one is the most important of the two and is how the code necessary for p5.js to work is brought to your website. Notice how the src
is set to an external URL. You don’t have to worry too much about this but, effectively, the p5 library code is being sent to you from this CDN (content delivery network) for your p5 code to then work.
The second <script>
is if you want to use p5 with sound interaction, so it’s not necessary if you don’t plan on using it.
Then, the third <script>
is just the file where you’ll put your p5 sketch code.
Understanding the p5.js Structure
Every p5.js “artpiece” is sometimes referred to a sketch and has two main functions that you need to define:
function setup() {
// This runs once at the beginning
createCanvas(400, 400);
background(220);
}
function draw() {
// This runs repeatedly, about 60 times per second
// Your animation code goes here
}
The setup()
function runs once when your program starts. It’s where you set initial settings like the canvas size.
The draw()
function runs continuously after setup()
, allowing for animation and interaction.
I’ll use an analogy to break this down.
Flowing Pipes
Imagine a closed loop of pipes with a pump in the center. In this loop, the liquid is constantly flowing as dictated by the pump in the loop.
Here, think of the your computer as the pump and the piping and liquid as p5.js.
When you fill up the pipes with water or soda or whatever else you like, that’s the purpose of the setup()
function. We’re just establishing the foundation for our sketch to work. This could be like introducing fonts, creating the “canvas” for a sketch to appear on, etc. It’s a process we do a single time just to get things working.
Now we have the constant flow. This is like the draw()
function. p5 is developed so that draw()
is activated 60 times a second. Like the loop, we start at the top of draw()
and work our way down. Then, when we get to the bottom we just loop back up to the top again.
You can think of the code you write inside your draw()
as switching in and out various pieces of pipes.
Say you want a red background. In your draw()
, simply write out:
draw() {
background(255, 0, 0);
}
There you go, you’ve just installed a piece of pipe that will make the output of your sketch have a red background! All the various “pipes” you can use and how to use them can be found on the p5.js Reference.
Understanding the draw()
function as something that is always running is crucial in coding your sketches properly. There are situations where you can make draw()
run a single time, but we’ll get into it later. Let’s start with some simple sketches.
Drawing Basic Shapes
First, let’s take a look at the basic skeleton for a p5 sketch:
// Each sketch has a setup() and draw()
function setup() {
// You'll also need a canvas to display your sketch
// The numbers are for width and height in pixels
createCanvas(400, 400);
}
function draw() {
// Grey background
background(240);
// Draw a circle
circle(100, 100, 50);
}
And now you should see a simple sketch of a circle on a grey canvas. Let’s take a closer look at what we’ve coded.
In our setup()
, we are creating a canvas with a width and height of 400 pixels.
Then, in our draw()
, we are:
- setting the background to grey
- drawing a circle at x: 100, y: 100, and diameter: 50
So the water is “flowing” through the pipes and will now output a circle on a grey background. Excellent! But this is a bit simple, what if we want something more complicated?
function setup() {
createCanvas(400, 400);
}
function draw() {
// Grey background
background(240);
// Red fill
fill(255, 0, 0);
// Draw a circle
circle(100, 100, 50);
// Blue fill
fill(0, 0, 255);
// Draw a rectangle
rect(200, 200, 100, 60);
// Green stroke
stroke(0, 255, 0);
// 5 pixel stroke weight
strokeWeight(5);
// Draw a line
line(50, 300, 350, 300);
}
Now let’s break down what we’re doing:
- Grey background
- Red fill color
- Circle x: 100, y:100, d: 50
- Blue fill color
- Rectangle x: 200, y:200, width: 100, height: 60
- Green stroke (line) color
- 5 pixel stroke weight (width)
- Line from x: 50, y: 300 to x: 350, y: 300
There are several key points here as well as a few things you should play around with.
Firstly, notice how the fill color has to be stated every time you want it changed. What happens when you remove the blue fill for the rectangle? The red fill gets applied!
This goes back to our flow analogy: the liquid “flowed” through the red-color changing pipe, drew a circle and drew a rectangle. Since the fill color changed, it will apply to everything below it!
Remember back when I mentioned we get to the end of our draw()
, we loop back up to the top? The same is happening here with our stroke color and weight! We declare the stroke as green with a weight of 5. Since the draw()
is constantly looping, these rules are applied to the circle and rectangle after the first run!
In p5, you can put noLoop()
at the end of your draw()
so that it does not loop forever. Now, the circle and rectangle don’t have a wide green stroke! This logic where draw()
constantly runs (without noLoop()
) is vital to understanding how p5 works and defines how you engage with the library.
Animation Basics
Animation in p5.js is created by changing variables over time while utilizing the looping of draw()
. Here’s a simple bouncing ball example:
let x = 0;
let speed = 3;
function setup() {
createCanvas(400, 200);
}
function draw() {
background(220);
// Draw the ball
fill(255, 0, 0);
circle(x, 100, 30);
// Update position
x = x + speed;
}
There are some good points to be made here. First, we define the variables x
and speed
outside our setup()
and draw()
. If they were inside setup()
you wouldn’t be able to access them in draw()
.
However, the most important distinction is that they are outside of draw()
. Think about it, if we had draw()
look like:
draw() {
let x = 0;
let speed = 3;
background(220);
// Draw the ball
fill(255, 0, 0);
circle(x, 100, 30);
// Update position
x = x + speed;
}
x
and speed
are constantly being set to 0 and 3! Since the let
keyword is inside draw()
, the variables are always being recreated with the original values and never change. Once we move the variables outside draw()
, the variables are stored and can be updated without being reset!
Every draw()
loop, x
will increase by the value of speed
(3) and get stored. Now in the next loop, the circle will be drawn using this new position and will look like it’s moving!
This is the fundamental concept of animation with p5. You are using the fact that draw()
loops to update some variable. Then, every object that uses that variable will appear to change when they are redrawn!
User Interaction
p5.js also makes it easy to create interactive sketches. Here’s an example of a circle that follows your mouse:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// Draw a circle at the mouse position
fill(255, 0, 0);
circle(mouseX, mouseY, 50);
}
mouseX
and mouseY
are variables given to you by p5. They simply just store the x and y position of the mouse cursor when it moves over the canvas. By drawing the circle at these positions, it will follow the mouse as it moves across the circle.
You can also respond to mouse clicks:
function setup() {
createCanvas(400, 400);
background(220);
}
function draw() {
// We don't redraw the background, so previous circles stay
}
function mousePressed() {
// Draw a circle when the mouse is pressed
fill(255, 0, 0);
circle(mouseX, mouseY, 30);
}
Like mouseX
and mouseY
, mousePressed()
is a separate function given to you by p5 that executes whenever the viewer clicks their mouse. It works more similarly to setup()
in that it does not loop and is run a single time on that mouse click. Here, it will draw a circle at the mouse position when the click happens.
This is another good example of understanding the “flow” of p5. Notice how we’ve put our background()
in our setup()
instead of draw()
. See what happens when you put background()
in draw()
. The sketch doesn’t seem to work, right?
What’s happening behind the scenes is that background()
technically just draws a rectangle with the full height and width of the canvas and the fill color you give it. When it is in draw()
, the background “rectangle” is constantly drawn so it is always on top of what is underneath it. Since a background is constantly applied, it smothers everything underneath it because it just stacks on top.
When we move background()
to setup()
, the “background” rectangle is drawn a single time. Now, each mouse click will draw a circle on top of the previous! This only works because there are no more redrawn backgrounds to hide the overlapping.
You can further test this by moving background()
into the top of mousePressed()
. Now, the circle will be properly drawn on top of the background without overlapping previous circles! Figuring out this logic is key to understanding p5. It’s also quite often a source of frustration and confusion, so be patient and diligent with it.
Next Steps
Once you’ve mastered the basics of p5.js, you can explore:
- Creating more complex animations
- Building interactive games
- Visualizing data
- Creating generative art
- Exploring the add-ons like p5.sound for audio projects
Conclusion
p5.js opens up a world of creative possibilities for the web. By understanding these fundamentals, you’re ready to start creating your own interactive digital art and visualizations. But don’t overwhelm yourself! p5 is vast and has a whole bunch of features.
Start small, experiment often, and most importantly, have fun with it! Creative coding is about expression and exploration, not just technical precision.