Arranging a Line of Items
Arranging items in a line – by width
This code draws a line of items – as many as necessary to reach the edge of the canvas. In this case, the items are circles. The code can be adapted to draw squares, or more complicated figures composed of multiple shapes.
The code draws as many shapes as will fit in the canvas width (x <= width), spaced 50 pixels apart (x += 50).
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
function draw() {
for (let x = 10; x <= width; x += 50) {
circle(x, 100, 40);
}
} Arranging items in a line – by item count
What if we want to draw a fixed number of items? This code draws exactly 20 items, no matter how wide the canvas is. It uses i to count the number of shapes, from 0 to 19.
function draw() {
let x = 10;
for (let i = 0; i < 20; i++) {
circle(x, 100, 40);
x += 50;
}
} Note: From here on, the definition of setup() is not shown. Each of the following code samples assumes that the sketch also contains a setup() function:
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
Geometric Progressions
The code above increases x by the same amount each step. This is an arithmetic progression.
We can also increase x by an increasing amount. This is a geometric progression.
function draw() {
let x = 10;
for (let i = 0; i < 20; i++) {
circle(x, 100, 40);
x *= 1.2;
}
} Changing the spacing is useful when the size changes too.
function draw() {
let x = 20;
let size = 5;
for (let i = 0; i < 20; i++) {
circle(x, 100, size);
x *= 1.15;
size *= 1.15;
}
} Accumulating versus deriving
Back to the arithmetic progression:
function draw() {
let x = 10;
for (let i = 10; i < 20; i++) {
circle(x, 100, 40);
x += 50;
}
} This strategy for computing the value of x accumulates a value. x starts out with a value (10); then each time through the loop, the value is updated.
An alternative to accumulation is to derive the value of x from scratch each time, directly from the value of i. The shape position is derived from the loop index. This has the same effect as the previous code, but it will allow us to plug in different functions besides the linear function used here. We’ll see that later.
function draw() {
for (let i = 0; i < 20; i++) {
let x = 10 + 50 * i;
circle(x, 100, 40);
}
}
Bending the line
So far, all the circles share the same y position. We can make the line slope by deriving y from i as well.
function draw() {
for (let i = 0; i < 20; i++) {
let x = 10 + 50 * i;
let y = 100 + 10 * i;
circle(x, y, 40);
}
} Try dragging the 10 in let y = 100 + 10 * i to change the slope of the line. Scrubbing it up to 20 (so the line reads let y = 100 + 20 * i) makes the line steeper; scrubbing it down to 5 (let y = 100 + 5 * i) makes it shallower. Click the ↺ button in the canvas to reset the values.
Waves
The payoff to using a function to compute the position is that we can use different functions, for different effects. For example, .
sin() returns a number between -1 and 1. Varying the y position by that much is barely detectable. (Try it.) This code multiplies the output of sin() by 20, to produce a number between -20 and 20, for a more pronounced wiggle. (It is similar to random(-20, 20), except that the change from one circle to the next is sinusoidal instead of random.)
function draw() {
for (let i = 0; i < 20; i++) {
let x = 10 + 50 * i;
let y = 100 + 20 * sin(i);
circle(x, y, 40);
}
} Instead of using an equation , we can use the map() function to do the same thing. Either y = 100 + map(sin(i), -1, 1, -20, 20) or y = map(sin(i), -1, 1, 80, 120) would work. The latter most clearly expresses the range of values (80 to 120) that will be assigned to y.
function draw() {
for (let i = 0; i < 20; i++) {
let x = 10 + 50 * i;
let y = map(sin(i), -1, 1, 80, 120);
circle(x, y, 40);
}
} We can also vary the size of each circle using cos(i), so that both position and size oscillate along the line:
function draw() {
for (let i = 0; i < 20; i++) {
let x = 10 + 50 * i;
let y = map(sin(i), -1, 1, 80, 120);
let size = 20 + 20 * cos(i);
circle(x, y, size);
}
} ©2020–2022 by Oliver Steele.