411 lines
9.6 KiB
Markdown
411 lines
9.6 KiB
Markdown
|
|
# Core API Reference
|
||
|
|
|
||
|
|
## Canvas Setup
|
||
|
|
|
||
|
|
### createCanvas()
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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.
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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.
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
let x = randomGaussian(0, 1); // mean=0, stddev=1
|
||
|
|
// Useful for natural-looking distributions
|
||
|
|
```
|
||
|
|
|
||
|
|
### Perlin Noise
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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()
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// 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:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
textWeight(700); // dynamic weight without loading multiple files
|
||
|
|
```
|
||
|
|
|
||
|
|
### textToContours() and textToModel()
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
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
|
||
|
|
|
||
|
|
```html
|
||
|
|
<script src="https://cdn.jsdelivr.net/npm/p5@2/lib/p5.min.js"></script>
|
||
|
|
```
|