Loops & Patterns
Use for and while loops to generate grids, rings, spirals, and repeating motifs.
The for loop
A for loop runs a block of code a set number of times:
for (let i = 0; i < 10; i++) {
// runs 10 times — i goes 0, 1, 2, ... 9
}
Draw 10 evenly-spaced circles across the canvas:
function setup() {
createCanvas(600, 200);
noLoop();
}
function draw() {
background(20);
noStroke();
fill(100, 200, 255);
for (let i = 0; i < 10; i++) {
let x = map(i, 0, 9, 40, width - 40);
circle(x, height / 2, 30);
}
}
Nested loops — grids
Two loops, one inside the other, generate a 2D grid:
function draw() {
background(20);
noStroke();
let cols = 12;
let rows = 8;
let cellW = width / cols;
let cellH = height / rows;
for (let col = 0; col < cols; col++) {
for (let row = 0; row < rows; row++) {
let x = col * cellW + cellW / 2;
let y = row * cellH + cellH / 2;
// Size based on distance from cursor
let d = dist(mouseX, mouseY, x, y);
let size = map(d, 0, 300, cellW * 0.9, 4);
fill(
map(col, 0, cols - 1, 50, 255),
map(row, 0, rows - 1, 50, 255),
200
);
circle(x, y, size);
}
}
}
Loop with step size
You’re not limited to i++. Change the increment:
// Lines every 20 pixels
for (let x = 0; x <= width; x += 20) {
line(x, 0, x, height);
}
// Count down
for (let i = 100; i > 0; i -= 10) {
circle(width / 2, height / 2, i * 2);
}
Concentric rings — a classic:
function draw() {
background(20);
noFill();
stroke(100, 200, 255, 80);
strokeWeight(1);
for (let r = 10; r < 300; r += 15) {
circle(width / 2, height / 2, r * 2);
}
}
while loop
Use while when you don’t know in advance how many iterations you need:
// Pack random circles without overlapping (basic attempt)
let circles = [];
while (circles.length < 50) {
let candidate = {
x: random(width),
y: random(height),
r: random(10, 40)
};
let valid = true;
for (let c of circles) {
if (dist(candidate.x, candidate.y, c.x, c.y) < candidate.r + c.r + 4) {
valid = false;
break;
}
}
if (valid) circles.push(candidate);
}
Be careful with
whileloops — if the condition never becomes false, you’ll freeze the browser. Always have a safe exit condition or a maximum iteration count.
Polar coordinates — rings and spirals
Instead of a grid (x, y), think in terms of angle and radius:
function setup() {
createCanvas(600, 600);
noLoop();
background(20);
}
function draw() {
translate(width / 2, height / 2);
noStroke();
let numDots = 120;
for (let i = 0; i < numDots; i++) {
let angle = TWO_PI / numDots * i;
let radius = map(i, 0, numDots, 40, 240);
let x = cos(angle) * radius;
let y = sin(angle) * radius;
colorMode(HSB, 360, 100, 100);
fill(map(i, 0, numDots, 0, 360), 80, 90);
circle(x, y, map(i, 0, numDots, 4, 14));
}
}
Change radius to a constant for a circle of dots. Use it as a growing value for a spiral.
Recursive patterns
A function can call itself to create fractal-like structures:
function setup() {
createCanvas(600, 600);
noLoop();
background(20);
stroke(100, 200, 255, 120);
noFill();
branches(width / 2, height - 20, -HALF_PI, 120);
}
function branches(x, y, angle, len) {
if (len < 5) return; // stop condition — essential!
let endX = x + cos(angle) * len;
let endY = y + sin(angle) * len;
strokeWeight(map(len, 5, 120, 0.5, 3));
line(x, y, endX, endY);
branches(endX, endY, angle - 0.4, len * 0.72);
branches(endX, endY, angle + 0.4, len * 0.72);
}
Loop-based animation
Use frameCount with a loop for animated patterns:
function draw() {
background(20);
translate(width / 2, height / 2);
noFill();
stroke(150, 100, 255, 80);
let t = frameCount * 0.008;
for (let i = 0; i < 60; i++) {
let angle = TWO_PI / 60 * i + t;
let r1 = 80 + sin(t * 2 + i * 0.2) * 40;
let r2 = 140 + cos(t + i * 0.15) * 50;
strokeWeight(0.8);
line(
cos(angle) * r1, sin(angle) * r1,
cos(angle + 0.2) * r2, sin(angle + 0.2) * r2
);
}
}
Key takeaways
for (let i = 0; i < n; i++)is the standard counting loop- Nested
forloops generate 2D grids - Change the step size (
i += 20) for spaced repetition - Polar coordinates (
cos(angle) * r,sin(angle) * r) produce circular/spiral arrangements - Recursive functions can generate tree and fractal structures — always include a stop condition
- Combine loops with
frameCountfor animated patterns