9.6 KiB
9.6 KiB
Core API Reference
Canvas Setup
createCanvas()
// 2D (default renderer)
createCanvas(1920, 1080);
// WebGL (3D, shaders)
createCanvas(1920, 1080, WEBGL);
// Responsive
createCanvas(windowWidth, windowHeight);
Pixel Density
High-DPI displays render at 2x by default. This doubles memory usage and halves performance.
// Force 1x for consistent export and performance
pixelDensity(1);
// Match display (default) — sharp on retina but expensive
pixelDensity(displayDensity());
// ALWAYS call before createCanvas()
function setup() {
pixelDensity(1); // first
createCanvas(1920, 1080); // second
}
For export, always pixelDensity(1) and use the exact target resolution. Never rely on device scaling for final output.
Responsive Resize
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
// Recreate offscreen buffers at new size
bgLayer = createGraphics(width, height);
// Reinitialize any size-dependent state
}
Coordinate System
P2D (Default)
- Origin: top-left (0, 0)
- X increases rightward
- Y increases downward
- Angles: radians by default,
angleMode(DEGREES)to switch
WEBGL
- Origin: center of canvas
- X increases rightward, Y increases upward, Z increases toward viewer
- To get P2D-like coordinates in WEBGL:
translate(-width/2, -height/2)
Draw Loop
function preload() {
// Load assets before setup — fonts, images, JSON, CSV
// Blocks execution until all loads complete
font = loadFont('font.otf');
img = loadImage('texture.png');
data = loadJSON('data.json');
}
function setup() {
// Runs once. Create canvas, initialize state.
createCanvas(1920, 1080);
colorMode(HSB, 360, 100, 100, 100);
randomSeed(CONFIG.seed);
noiseSeed(CONFIG.seed);
}
function draw() {
// Runs every frame (default 60fps).
// Set frameRate(30) in setup() to change.
// Call noLoop() for static sketches (render once).
}
Frame Control
frameRate(30); // set target FPS
noLoop(); // stop draw loop (static pieces)
loop(); // restart draw loop
redraw(); // call draw() once (manual refresh)
frameCount // frames since start (integer)
deltaTime // milliseconds since last frame (float)
millis() // milliseconds since sketch started
Transform Stack
Every transform is cumulative. Use push()/pop() to isolate.
push();
translate(width / 2, height / 2);
rotate(angle);
scale(1.5);
// draw something at transformed position
ellipse(0, 0, 100, 100);
pop();
// back to original coordinate system
Transform Functions
| Function | Effect |
|---|---|
translate(x, y) |
Move origin |
rotate(angle) |
Rotate around origin (radians) |
scale(s) / scale(sx, sy) |
Scale from origin |
shearX(angle) |
Skew X axis |
shearY(angle) |
Skew Y axis |
applyMatrix(a, b, c, d, e, f) |
Arbitrary 2D affine transform |
resetMatrix() |
Clear all transforms |
Composition Pattern: Rotate Around Center
push();
translate(cx, cy); // move origin to center
rotate(angle); // rotate around that center
translate(-cx, -cy); // move origin back
// draw at original coordinates, but rotated around (cx, cy)
rect(cx - 50, cy - 50, 100, 100);
pop();
Offscreen Buffers (createGraphics)
Offscreen buffers are separate canvases you can draw to and composite. Essential for:
- Layered composition — background, midground, foreground
- Persistent trails — draw to buffer, fade with semi-transparent rect, never clear
- Masking — draw mask to buffer, apply with
image()or pixel operations - Post-processing — render scene to buffer, apply effects, draw to main canvas
let layer;
function setup() {
createCanvas(1920, 1080);
layer = createGraphics(width, height);
}
function draw() {
// Draw to offscreen buffer
layer.background(0, 10); // semi-transparent clear = trails
layer.fill(255);
layer.ellipse(mouseX, mouseY, 20);
// Composite to main canvas
image(layer, 0, 0);
}
Trail Effect Pattern
let trailBuffer;
function setup() {
createCanvas(1920, 1080);
trailBuffer = createGraphics(width, height);
trailBuffer.background(0);
}
function draw() {
// Fade previous frame (lower alpha = longer trails)
trailBuffer.noStroke();
trailBuffer.fill(0, 0, 0, 15); // RGBA — 15/255 alpha
trailBuffer.rect(0, 0, width, height);
// Draw new content
trailBuffer.fill(255);
trailBuffer.ellipse(mouseX, mouseY, 10);
// Show
image(trailBuffer, 0, 0);
}
Multi-Layer Composition
let bgLayer, contentLayer, fxLayer;
function setup() {
createCanvas(1920, 1080);
bgLayer = createGraphics(width, height);
contentLayer = createGraphics(width, height);
fxLayer = createGraphics(width, height);
}
function draw() {
// Background — drawn once or slowly evolving
renderBackground(bgLayer);
// Content — main visual elements
contentLayer.clear();
renderContent(contentLayer);
// FX — overlays, vignettes, grain
fxLayer.clear();
renderEffects(fxLayer);
// Composite with blend modes
image(bgLayer, 0, 0);
blendMode(ADD);
image(contentLayer, 0, 0);
blendMode(MULTIPLY);
image(fxLayer, 0, 0);
blendMode(BLEND); // reset
}
Composition Patterns
Grid Layout
let cols = 10, rows = 10;
let cellW = width / cols;
let cellH = height / rows;
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
let cx = cellW * (i + 0.5);
let cy = cellH * (j + 0.5);
// draw element at (cx, cy) within cell size (cellW, cellH)
}
}
Radial Layout
let n = 12;
for (let i = 0; i < n; i++) {
let angle = TWO_PI * i / n;
let r = 300;
let x = width/2 + cos(angle) * r;
let y = height/2 + sin(angle) * r;
// draw element at (x, y)
}
Golden Ratio Spiral
let phi = (1 + sqrt(5)) / 2;
let n = 500;
for (let i = 0; i < n; i++) {
let angle = i * TWO_PI / (phi * phi);
let r = sqrt(i) * 10;
let x = width/2 + cos(angle) * r;
let y = height/2 + sin(angle) * r;
let size = map(i, 0, n, 8, 2);
ellipse(x, y, size);
}
Margin-Aware Composition
const MARGIN = 80; // pixels from edge
const drawW = width - 2 * MARGIN;
const drawH = height - 2 * MARGIN;
// Map normalized [0,1] coordinates to drawable area
function mapX(t) { return MARGIN + t * drawW; }
function mapY(t) { return MARGIN + t * drawH; }
Random and Noise
Seeded Random
randomSeed(42);
let x = random(100); // always same value for seed 42
let y = random(-1, 1); // range
let item = random(myArray); // random element
Gaussian Random
let x = randomGaussian(0, 1); // mean=0, stddev=1
// Useful for natural-looking distributions
Perlin Noise
noiseSeed(42);
noiseDetail(4, 0.5); // 4 octaves, 0.5 falloff
let v = noise(x * 0.01, y * 0.01); // returns 0.0 to 1.0
// Scale factor (0.01) controls feature size — smaller = smoother
Math Utilities
| Function | Description |
|---|---|
map(v, lo1, hi1, lo2, hi2) |
Remap value between ranges |
constrain(v, lo, hi) |
Clamp to range |
lerp(a, b, t) |
Linear interpolation |
norm(v, lo, hi) |
Normalize to 0-1 |
dist(x1, y1, x2, y2) |
Euclidean distance |
mag(x, y) |
Vector magnitude |
abs(), ceil(), floor(), round() |
Standard math |
sq(n), sqrt(n), pow(b, e) |
Powers |
sin(), cos(), tan(), atan2() |
Trig (radians) |
degrees(r), radians(d) |
Angle conversion |
fract(n) |
Fractional part |
p5.js 2.0 Changes
p5.js 2.0 (released Apr 2025, current: 2.2) introduces breaking changes. The p5.js editor defaults to 1.x until Aug 2026. Use 2.x only when you need its features.
async setup() replaces preload()
// p5.js 1.x
let img;
function preload() { img = loadImage('cat.jpg'); }
function setup() { createCanvas(800, 800); }
// p5.js 2.x
let img;
async function setup() {
createCanvas(800, 800);
img = await loadImage('cat.jpg');
}
New Color Modes
colorMode(OKLCH); // perceptually uniform — better gradients
// L: 0-1 (lightness), C: 0-0.4 (chroma), H: 0-360 (hue)
fill(0.7, 0.15, 200); // medium-bright saturated blue
colorMode(OKLAB); // perceptually uniform, no hue angle
colorMode(HWB); // Hue-Whiteness-Blackness
splineVertex() replaces curveVertex()
No more doubling first/last control points:
// p5.js 1.x — must repeat first and last
beginShape();
curveVertex(pts[0].x, pts[0].y); // doubled
for (let p of pts) curveVertex(p.x, p.y);
curveVertex(pts[pts.length-1].x, pts[pts.length-1].y); // doubled
endShape();
// p5.js 2.x — clean
beginShape();
for (let p of pts) splineVertex(p.x, p.y);
endShape();
Shader .modify() API
Modify built-in shaders without writing full GLSL:
let myShader = baseMaterialShader().modify({
vertexDeclarations: 'uniform float uTime;',
'vec4 getWorldPosition': `(vec4 pos) {
pos.y += sin(pos.x * 0.1 + uTime) * 20.0;
return pos;
}`
});
Variable Fonts
textWeight(700); // dynamic weight without loading multiple files
textToContours() and textToModel()
let contours = font.textToContours('HELLO', 0, 0, 200);
// Returns array of contour arrays (closed paths)
let geo = font.textToModel('HELLO', 0, 0, 200);
// Returns p5.Geometry for 3D extruded text
CDN for p5.js 2.x
<script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script>