Canvas & Coordinates
Understand Processing's coordinate system, learn to use size() and fullScreen(), and transform the canvas with translate(), rotate(), and scale().
Setting the Canvas Size
Every sketch starts with a size declaration in setup():
void setup() {
size(800, 600);
}
The arguments are always size(width, height). The resulting canvas is 800 pixels wide and 600 pixels tall. Processing stores these values in the built-in variables width and height — use them instead of hardcoding numbers, and your sketch becomes easier to resize later:
void setup() {
size(800, 600);
}
void draw() {
// Draw a line from corner to corner
line(0, 0, width, height);
line(width, 0, 0, height);
}
For fullscreen output — useful for installations or presentations — use fullScreen() instead of size():
void setup() {
fullScreen();
}
fullScreen() sets the canvas to fill the entire primary monitor. If you have multiple monitors, fullScreen(2) targets the second display. After calling fullScreen(), the width and height variables reflect the actual screen dimensions.
The Coordinate System
Processing uses a screen coordinate system where:
- (0, 0) is the top-left corner
- x increases to the right
- y increases downward
This is different from the mathematical coordinate systems you may have encountered, where y increases upward. It matches how screens are addressed at the hardware level.
(0,0)──────────────▶ x
│
│
│
▼
y
For a 400x400 canvas:
- Top-left corner:
(0, 0) - Top-right corner:
(400, 0)— note: actually(399, 0)for the last addressable pixel - Bottom-left corner:
(0, 400) - Bottom-right corner:
(400, 400) - Center:
(200, 200)— or use(width/2, height/2)to avoid magic numbers
This takes some getting used to if you’re coming from mathematics, but it quickly becomes natural.
Pixels vs Logical Coordinates
On standard displays, one unit in Processing equals one pixel. On high-DPI displays (like Apple Retina screens), Processing can run at increased density. For most purposes in these tutorials, you can treat Processing coordinates as pixel coordinates.
The pixelDensity() function lets you explicitly control this:
void setup() {
size(400, 400);
pixelDensity(2); // render at 2x for crisp output on Retina
}
You don’t need to think about this until you’re outputting high-quality print or video work.
Transforming the Coordinate System
Rather than calculating every position by hand, Processing lets you move, rotate, and scale the coordinate system itself. This is called a transformation and is one of the most powerful tools in Processing.
translate()
translate(x, y) moves the origin point (0, 0) to a new location. After translating, everything you draw is positioned relative to the new origin:
void setup() {
size(400, 400);
}
void draw() {
background(240);
// Without translation: rectangle at top-left
fill(200, 50, 50);
rect(0, 0, 60, 60);
// Move origin to center, then draw at (0,0) — appears at center
translate(width / 2, height / 2);
fill(50, 100, 200);
rect(0, 0, 60, 60);
}
rotate()
rotate(angle) rotates the coordinate system. The angle is measured in radians, not degrees. Use radians() to convert if you think in degrees:
void draw() {
background(240);
translate(width / 2, height / 2); // move origin to center
rotate(radians(45)); // rotate 45 degrees
rect(-30, -30, 60, 60); // draw square centered on origin
}
To animate rotation, use frameCount — a variable that increments by 1 each frame:
void draw() {
background(240);
translate(width / 2, height / 2);
rotate(frameCount * 0.02); // slowly spin
rect(-40, -40, 80, 80);
}
scale()
scale(factor) zooms the coordinate system. scale(2) makes everything draw twice as large. scale(0.5) makes everything half size:
void draw() {
background(240);
translate(width / 2, height / 2);
scale(2.0); // everything 2x larger
rect(-40, -40, 80, 80);
}
You can scale x and y independently: scale(2.0, 0.5) stretches horizontally and squishes vertically.
pushMatrix() and popMatrix()
Here’s the critical detail: translate(), rotate(), and scale() are cumulative and persistent within a single draw() call. If you call translate(100, 100) and then translate(50, 0), the origin is now at (150, 100).
To isolate transformations — apply them to one object without affecting others — use pushMatrix() and popMatrix(). Think of them as save and restore for the coordinate system:
void draw() {
background(240);
// Draw a square at top-left, no transformation
fill(200, 50, 50);
rect(20, 20, 60, 60);
// Save the current coordinate state
pushMatrix();
translate(width / 2, height / 2);
rotate(radians(45));
fill(50, 100, 200);
rect(-30, -30, 60, 60);
// Restore coordinate state — next shapes are unaffected by the above
popMatrix();
// This rect draws at the normal coordinate origin
fill(50, 200, 50);
rect(20, height - 80, 60, 60);
}
You can nest pushMatrix() / popMatrix() pairs as deep as you need.
Example: Grid of Circles with Nested Loops
Nested for loops combined with translation let you tile shapes across the canvas efficiently. Here’s a grid of circles that grow based on their row and column:
int cols = 8;
int rows = 8;
float cellSize;
void setup() {
size(480, 480);
cellSize = width / cols;
noStroke();
}
void draw() {
background(20);
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
float x = col * cellSize + cellSize / 2;
float y = row * cellSize + cellSize / 2;
// Size based on distance from mouse
float d = dist(mouseX, mouseY, x, y);
float diameter = map(d, 0, width, cellSize * 0.9, 5);
fill(180, 100, 255);
ellipse(x, y, diameter, diameter);
}
}
}
This uses dist() to calculate the distance between each circle’s center and the mouse position, then map() to scale that distance into a circle diameter. Circles near the mouse are large; circles far away are small. Move your mouse across the canvas to see the effect.
Two new functions used here:
dist(x1, y1, x2, y2)— returns the pixel distance between two pointsmap(value, start1, stop1, start2, stop2)— re-maps a value from one range to another
You’ll use both constantly in Processing. map() in particular is one of the most useful functions in the entire API.
Combining Transforms in Practice
The translate → draw → popMatrix pattern is the building block for more complex scenes. In the tutorials ahead, you’ll use it to rotate individual shapes in a composition, build orbital animations, and draw shapes that spin around their own centers rather than around the canvas origin.
Next up: you’ll learn the complete set of drawing primitives available in Processing, from basic rectangles to custom polygons using beginShape() and vertex().