Back

HTML5 Canvas Transformations: Translate, Rotate, and Scale

7 min read

HTML5 Canvas Transformations: Translate, Rotate, and Scale

Once you have mastered drawing basic shapes, the next essential skill in canvas game development is understanding Transformations. This includes moving, rotating, and scaling (or flipping) objects.

The most important concept in Canvas transformations is that you don't rotate or scale the shape itself. Instead, you transform the entire canvas coordinate system before drawing the shape, and then you revert the coordinate system back. Let's see how!

1. State Management: save() and restore()

Since transformations affect the entire canvas globally, you must use save() to store the current canvas state, apply your transformations, draw, and finally use restore() to bring the canvas back to normal.

ctx.save(); // Save the default un-transformed state

// ... Apply transformations and draw here ...

ctx.restore(); // Revert back to the un-transformed state

2. Moving the Origin: translate(x, y)

By default, the origin (0, 0) is at the top-left corner of the canvas. translate moves this origin point. If you want to rotate an object around its center, you must first move the coordinate system's origin to the exact center of where you want to draw the object.

const x = 100; // Position X
const y = 100; // Position Y
const width = 50;
const height = 50;

ctx.save();
ctx.translate(x + width / 2, y + height / 2); // Move origin to object's center

// Now, drawing at (0, 0) is actually drawing exactly at our translated center
ctx.fillStyle = 'blue';

// We must draw from -width/2, -height/2 because the origin is exactly in the middle!
ctx.fillRect(-width / 2, -height / 2, width, height); 

ctx.restore(); // Return origin to top-left (0, 0)

3. Rotating Shapes: rotate(angle)

ctx.rotate() rotates the grid around the current (0, 0) origin point. This is why we almost always translate the origin to the center of the shape first. Angles must be in radians, not degrees.

const angleInDegrees = 45;
const angleInRadians = angleInDegrees * Math.PI / 180;

ctx.save();
// 1. Move origin to center point
ctx.translate(150, 150);

// 2. Rotate the grid
ctx.rotate(angleInRadians);

// 3. Draw shape centered at the new origin (0, 0)
ctx.fillStyle = 'red';
// Draws a 50x50 rotated square
ctx.fillRect(-25, -25, 50, 50); 
ctx.restore();

4. Scaling and Flipping: scale(x, y)

ctx.scale(x, y) scales the current grid. x: 2 makes things twice as wide. x: 0.5 makes them half size.

A very common trick in game development is to flip an image or shape horizontally (like a character turning left or right). You can do this by using a negative scale!

ctx.save();
// 1. Move origin to the object's center first
ctx.translate(250, 200);

// 2. Flip horizontally (x = -1) and keep vertical scale normal (y = 1)
ctx.scale(-1, 1);

// 3. Draw element
ctx.font = '30px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// The text will be drawn backwards (flipped) like a mirror
ctx.fillText('FLIPPED!', 0, 0); 
ctx.restore();