Quickstart: Building Interactive Graphics with p5.js
Project Initialization
p5.js can be integrated into a web environment via CDN for rapid prototyping or installed through package managers for production builds.
CDN Integration:
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
Package Manager Installation:
npm install p5
import { createCanvas, background } from 'p5';
Core Rendering Pipeline
All p5.js applications revolve around two primary lifecycle functions that establish the rendering context and manage continuous redraws.
setup(): Executes once at application launch. Used for initializing canvas dimensions, configuring scene properties, and loading initial assets.draw(): Executes sequantially aftersetup()completes. Runs by default at 60 frames per second (FPS). Acts as the animation loop where frame-by-frame updates occur. Execution frequency can be adjusted usingframeRate(n)or halted withnoLoop().
Basic structure:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// Frame rendering logic here
}
Drawing Two-Dimensional Shapes
Coordinate systems in p5.js follow a top-left origin (0, 0). X increases to the right, Y increases downward.
Points and Lines
Points require explicit stroke thickness to become visible. Lines connect two coordinate pairs.
function setup() {
createCanvas(300, 300);
}
function draw() {
background(240);
stroke(80);
strokeWeight(4);
point(150, 150);
line(50, 50, 250, 250);
line(250, 50, 50, 250);
}
Polygons and Quadrilaterals
Triangles require three vertex coordinates. Rectangles can be drawn with fixed corners or rounded edges.
function setup() {
createCanvas(400, 300);
}
function draw() {
background(255);
noFill();
stroke(100);
triangle(100, 50, 200, 200, 50, 200);
fill(200, 50, 50);
rectMode(CENTER);
rect(300, 150, 120, 80, 15); // Rounded rectangle
}
Circles and Ellipses
Circles use diameter, while ellipses accept separate width and height parameters.
function setup() {
createCanvas(500, 300);
}
function draw() {
background(245);
strokeWeight(2);
stroke(50, 50, 100);
fill(180, 220, 150);
circle(150, 150, 120); // Diameter-based
ellipse(350, 150, 200, 100); // Width & Height
}
Arcs and Curves
Arcs are defined by start and stop angles measured in radians. The drawing mode determines whether the arc is open, closed with a straight line, or filled as a pie slice.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(20);
translate(200, 200);
stroke(255);
strokeWeight(3);
arc(0, 0, 250, 250, 0, HALF_PI, PIE);
arc(150, -150, 200, 200, PI * 0.5, PI * 1.5, OPEN);
}
Visual Styling and Color Systems
Rendering attributes apply globally until explicitly changed. Use push() and pop() to isolate style changes.
Color Modes
p5.js supports multiple color representations. Global state must be set before applying colors.
function setup() {
createCanvas(400, 300);
// Switch to HSB (Hue, Saturation, Brightness)
colorMode(HSB, 360, 100, 100, 1);
background(200, 20, 90); // Blue sky base
// Draw shapes with different color modes applied locally
push();
colorMode(RGB, 255);
fill(255, 0, 0, 0.7);
noStroke();
rect(50, 50, 150, 150);
pop();
// Grayscale mode (default)
fill(180);
square(250, 100, 100);
}
Stroke and Fill Controls
fill(r, g, b, alpha): Sets interior polygon color. Defaults to white if omitted.stroke(r, g, b, alpha): Defines outline color. Defaults to black.noFill()/noStroke(): Disables interior filling or outlining entire.strokeWeight(n): Adjusts line thickness and point size.
function setup() {
createCanvas(300, 300);
}
function draw() {
background(250);
push();
fill(60, 100, 200, 0.6);
stroke(20);
strokeWeight(2);
circle(100, 150, 100);
pop();
push();
noFill();
stroke(200, 50, 50);
strokeWeight(6);
quad(180, 80, 280, 80, 250, 220, 150, 220);
pop();
}
Typography Handling
Text placement anchors at the baseline's left edge. Bounding boxes can restrict overflow.
function setup() {
createCanvas(400, 300);
textFont('Courier');
}
function draw() {
background(240);
textAlign(CENTER, CENTER);
textSize(32);
fill(30);
text("Rendered Text Block", 200, 100);
// Constraining text within a virtual box
textAlign(LEFT, TOP);
textSize(16);
fill(100);
text("Wrapped content automatically adjusts based on x2 boundaries.", 40, 180, 200, 80);
}
Asset Management
External media like images or audio must load asynchronously to prevent blocking the render thread.
let sceneAsset;
let assetLoaded = false;
function preload() {
sceneAsset = loadImage('assets/background.png');
}
function setup() {
createCanvas(600, 400);
assetLoaded = true;
}
function draw() {
if (!assetLoaded) return;
background(240);
image(sceneAsset, 0, 0, width, height);
fill(0);
textSize(14);
text(`Image Dimensions: ${sceneAsset.width}x${sceneAsset.height}`, 20, height - 30);
}
State-Driven Interactivity and Animation
Continuous motion relies on updating positional variables each frame and redrawing the canvas context.
Event Detection
Global boolean flags track input state during the render loop.
function setup() {
createCanvas(500, 300);
}
function draw() {
// Dynamic background based on interaction
if (mouseIsPressed) {
background(40, 60, 120);
} else {
background(240);
}
if (keyIsPressed) {
fill(200, 50, 50);
} else {
fill(50);
}
noStroke();
ellipse(width / 2, height / 2, 80);
}
Coordinate Tracking and Motion
Mouse position (mouseX, mouseY) can drive element placement. To prevent visual artifacts during movement, clear the previous frame before redrawing.
let targetPos = { x: 0, y: 0 };
let currentPos = { x: 0, y: 0 };
function setup() {
createCanvas(600, 400);
targetPos.x = mouseX;
targetPos.y = mouseY;
}
function draw() {
// Clear screen for next frame
background(255);
// Update tracking targets
targetPos.x = mouseX;
targetPos.y = mouseY;
// Smooth interpolation toward target
lerpVal = 0.08;
currentPos.x = lerp(currentPos.x, targetPos.x, lerpVal);
currentPos.y = lerp(currentPos.y, targetPos.y, lerpVal);
// Render following element
fill(80, 120, 200, 150);
stroke(20);
strokeWeight(1);
circle(currentPos.x, currentPos.y, 60);
// Draw trajectory trail
noFill();
stroke(200, 100);
arc(currentPos.x - 40, currentPos.y, 100, 100, -HALF_PI, 0);
}
By leveraging these core primitives and lifecycle controls, developers can construct complex generative visuals, data-driven charts, and interactive installations without leaving the browser environment.