Frame Loop
A p5.js sketch is organized around a small set of functions that together define a frame loop—the mechanism that repeatedly updates and renders the display.
In most programming languages, execution begins at a single entry point—often a main function—and then proceeds sequentially, terminating unless the programmer explicitly defines a loop. This idea is commonly described as the program’s entry point
(see: ).
p5.js follows the same principle, but adapts it to interactive graphics: instead of exposing a user-defined main, the library provides a built-in entry point that initializes the environment and repeatedly calls draw() for you.
Conceptually, a p5.js sketch behaves as if it were driven by an internal main loop:
// conceptual model (not actual p5.js code)
function main() {
setup() // run once
while (true) { // animation loop
draw() // render next frame
}
}You never write this loop yourself—p5.js manages it internally. Your task is simply to define what happens per frame.
Core frame-loop functions
setup()– Runs once, acting as the sketch’s initialization entry point.draw()– Runs continuously, defining the sketch’s frame-by-frame behavior.
Additional sketch functions
- Interactive functions – Triggered by user events such as mouse, keyboard, or touch.
- Custom functions – Reusable helpers for drawing or organizing logic.
Here’s a minimal frame-loop structure in p5.js:
function setup() {
// Set up the canvas and initialize variables
}
function draw() {
// Frame loop: update and render each frame
}
// Interactive functions (mouse, keyboard, touch)
function mouseClicked() {
// Read mouseX and mouseY to capture click position
// Respond to the click
}
// Custom functions
function drawCircle(x, y, size, color) {
// Draw a circle with the given parameters
}Setup
The setup() function runs once at the start of the program. It is used to:
- Define the canvas size with
createCanvas(width, height). - Initialize variables and objects used throughout the sketch.
Example:
function setup() {
createCanvas(400, 400);
background(220); // Light gray background
}This creates a 400×400 canvas with a light gray background.
setup() as async and use await loadImage(...), await loadFont(...), etc.Asset Loading Example
Here’s an example that loads an image and uses it as the background:
Code Explanation
let pola;
async function setup() {
createCanvas(300, 300);
pola = await loadImage('pola.jpg');
background(pola);
}Draw
The draw() function implements the frame loop: it runs continuously, typically 60 times per second, updating the sketch at each frame. Unlike setup(), which runs once, draw() maintains the sketch’s ongoing behavior.
Continuous Drawing
By default, drawings in draw() accumulate over time—previous frames remain visible unless cleared. This produces a trailing effect, as in the example below where a red circle follows the mouse:
Code Explanation
function setup() {
createCanvas(300, 300);
}
function draw() {
fill(0, 255, 0);
circle(100, 200, 80);
fill(0, 0, 255);
circle(200, 200, 80);
fill(255, 0, 0, 25);
circle(mouseX, mouseY, 80);
}
Smooth Refresh
To avoid visual accumulation and redraw the scene cleanly every frame, call background() at the start of draw():
Code Explanation
function setup() {
createCanvas(300, 300);
}
function draw() {
background(70);
fill(0, 255, 0);
circle(100, 200, 80);
fill(0, 0, 255);
circle(200, 200, 80);
fill(255, 0, 0, 125);
circle(mouseX, mouseY, 80);
}
background()resets the frame, ensuring clean animation.- Without it, frames accumulate and create motion trails.
Arrays
When storing several related values—such as multiple positions—it’s more convenient to use an array than multiple separate variables.
Code Explanation
let positions = [50, 100, 150]; // store 3 x-coordinates
function setup() {
createCanvas(300, 300);
}
function draw() {
background(220);
// draw a circle for each position
for (let i = 0; i < positions.length; i++) {
circle(positions[i], height / 2, 20);
}
}Interactive Functions
Interactive functions such as mouseClicked(), mouseMoved(), and keyPressed() run automatically when their associated events occur. They complement the frame loop by reacting to user input.
Mouse and Keyboard Example
(Click anywhere to reposition the red circle; press any key to reset it.)
Code Explanation
let pola;
let redX, redY;
async function setup() {
createCanvas(300, 300);
pola = await loadImage('pola.jpg');
redX = width / 2;
redY = height / 2;
}
function draw() {
background(pola);
fill(0, 255, 0);
circle(100, 200, 80);
fill(0, 0, 255);
circle(200, 200, 80);
fill(255, 0, 0, 125);
circle(redX, redY, 80);
}
function mouseClicked() {
redX = mouseX;
redY = mouseY;
}
function keyPressed() {
redX = width / 2;
redY = height / 2;
}Custom Functions
To organize your sketch, you can define custom helper functions:
function drawCircle(size, color, x = width / 2, y = height / 2) {
push();
fill(color);
circle(x, y, size);
pop();
}You can call them inside the frame loop or whenever needed:
function draw() {
background(pola);
drawCircle(80, color(0, 255, 0), 100, 200);
drawCircle(80, color(0, 0, 255), 200, 200);
drawCircle(80, color(255, 0, 0, 125), mouseX, mouseY);
}Custom functions make sketches modular, readable, and reusable.
Further Reading
📌 p5.js Reference – Learn more about the frame loop (setup() and draw()), event handling, and loading assets.