HTML5 canvas - part 2: State
Tags: javascript, programming, tutorial, canvas
Published: 2018-05-17 07:01:59

---
title: HTML5 canvas - part 2: State
published: true
description: Second part of a series of articles to dive onto HTML5 canvas. Let's see available tools to change canvas state.
tags: javascript, programming, tutorial, canvas
cover_image: //thepracticaldev.s3.amazonaws.com/i/jdmy6rw4g3r6t8rxnlur.png
---

# Changing the state of a canvas

In the [first part](//dev.to/gmartigny/html5-canvas---part-1-drawing-4bc5), we have seen how drawing the same frame every loop is boring.
This time, we're going to look at what's available to turn this static black rectangle into a cute little moving black rectangle.

## Transforms

Remember how we previously see that paths can be stored in variable for reuse ?
Well, it has one tiny pitfall: you can not change it's position afterwards.

If we can not change the path position, let's change the canvas position !

### Disclaimer

All modification of the canvas state are permanent and cumulative. Imagine you move by 10px then move by 20 px, you've move a total of 30px and not 20px (as you could expect from CSS for example). So, if you go this way, you need to revert the state every time you change it.
Of course, the canvas API allow that with `save` and `restore`.

```js
ctx.save(); // Save the canvas' state

// Here goes as many changes as we want

ctx.restore(); // Restore to the last saved canvas' state
```

### [Translate](//developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate)

Pretty straightforwards, `translate` move the canvas (the canvas' context not the canvas' node).

{% codepen //codepen.io/GMartigny/embed/YLOzwO/?height=500&default-tab=js,result&embed-version=2#%}

In the example, I set the path position to `[0, 0]` and use a custom function `getPositions` then `translate` to move the canvas to a defined position. Finally, I surround all that with `save` and `restore`.

### [Rotate](//developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rotate)

You guessed it, `rotate` turn the canvas around. Here, things can get messy.
First, you have to remember that the expect angle is clockwise in radian (0: nothing, PI: half a turn, 2 * PI: full rotation).
Next, you can not define the rotation center, it's always the origin (0, 0). If you want to use another rotation center, you have to translate the canvas first.
Let's say we want to rotate by 45° angle from the rectangle center.

{% codepen //codepen.io/GMartigny/embed/vjzYPo/?height=500&default-tab=js,result&embed-version=2#%}

> What's going on with the cropped corners ?

I'm starting to overflow the canvas, but let's not worry with that for now.

### [Scale](//developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale)

Work almost like `rotate`. Again, you can't define a scale center, so you have to handle it yourself.

### [Transform](//developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform)

This function allow you to scale, skew and translate in one call. It's really awkward to use. However, it's the only way to skew. Sooo, that's something ...

## Canvas size

By default, a canvas element is (300x150)px. If you try change it's size with CSS, it will be stretch. However, using the node's attributes `width` and `height` will increase the it's size. Most of the time, it's easier to do it with Javascript.
Also, a canvas element default display is `"inline"`, which is rarely what you want.

Finally, let's dynamically change the values returned by `getPositions` and `getRotation` to have a little animation.

{% codepen //codepen.io/GMartigny/embed/MGqaZE/?height=500&default-tab=js,result&embed-version=2#%}

Here's what changed :
 - Add CSS to make the canvas full-page and grey
 - Increment a variable `i` every frame and passed it to `getPositions` and `getRotation`
 - Add some maths to `getPositions` and `getRotation`
 - Make all variable a ratio of canvas size

> Ok, this is moving, but still kind of sad.

I completely agree with you, imaginary allegory of my reader, hopefully, we'll see in [part 3 how to deal with images](//dev.to/gmartigny/html5-canvas---part-3-images-28ig).

In the meantime, you can try to add a "wobble" effect on the rectangle with `scale` and `Math.cos`.

See ya !