Step 1

The Problem: Drawing Concentric Circles

Let's say we want to draw a set of concentric circles — rings that all share the same center point but get smaller as they go inward. We know two things:

The biggest circle (the outer ring) should have a diameter of 350 px. The smallest circle (the inner ring) should have a diameter of 50 px.

If we only want 2 circles, it's easy — one is 350 and the other is 50. Here's what that looks like:

The easy case — 2 circles

That's straightforward — we only need two sizes and we already know them. But what if we want 3 circles? Or 7? How do we figure out the diameter for each circle so they are evenly spaced between 350 and 50?

We could try to do the math by hand every time… but that gets tedious fast. What we really need is a way to say: "I'm on circle number 3 out of 7 — what should my diameter be?"

Step 2

The Manual Way (So You Appreciate map!)

Let's try doing this by hand with 3 circles. Our range is 350 (max) down to 50 (min). That's a total span of 300 px.

With 3 circles, we have 2 gaps between them (always numCircles - 1 gaps). So each gap is 300 / 2 = 150 px.

Circle #iCalculationDiameter
1st (outer)0350 - (0 × 150)350 px
2nd (middle)1350 - (1 × 150)200 px
3rd (inner)2350 - (2 × 150)50 px

That works! But imagine doing this every time the number of circles changes. With 7 circles, or a random number? That's where map() comes in — it does all of this math for you.

Step 3

Enter map() — Your Automatic Translator

Think of map() as a translator between two number lines. You give it a value on one number line, and it tells you where that value falls on a different number line.

map(value, start1, stop1, start2, stop2)
value — The number you want to convert (our loop counter i).
start1, stop1 — The range your value lives in (e.g., 0 to numCircles - 1).
start2, stop2 — The range you want to translate into (e.g., 350 to 50).

So in our code, the call looks like this:

let currentDiameter = map(i, 0, numCircles - 1, 350, 50); // When i = 0 (first circle) → diameter = 350 (the biggest) // When i = last → diameter = 50 (the smallest) // Everything in between → evenly spaced!
Key insight: Because the output range goes from 350 down to 50, as i increases, the diameter decreases. This is what draws the circles from the outside in.

Step 4

See It: The Two Number Lines

Use the slider below to change the number of circles. Watch how map() translates each loop index i (the top number line) into a diameter (the bottom number line). The connecting lines show you exactly how each value maps.

Mapping idiameter

Step 5

See It: The Circles on the Canvas

Now let's see the actual result. Below is a live p5.js canvas drawing the concentric circles using the map() values from above. Adjust the slider and watch the rings update in real time.

Result — concentric circles

Notice how adding more circles makes the spacing tighter, and fewer circles makes the spacing wider. map() handles the math automatically every time!

Open Code Demo in p5.js Editor →