DEV Community

Cover image for HTML5 canvas - part 2: State
Guillaume Martigny
Guillaume Martigny

Posted on • Edited on

HTML5 canvas - part 2: State

Changing the state of a canvas

In the first part, 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.

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

// Here goes as many changes as we want

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

Translate

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

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

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.

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

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

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.

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.

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

See ya !

Top comments (0)