HTML5 canvas - part 2: State
Guillaume Martigny May 17 Updated on May 22, 2018
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.
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 !
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
ctx.save(); // Save the canvas' state // Here goes as many changes as we want ctx.restore(); // Restore to the last saved canvas' state
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
translate to move the canvas to a defined position. Finally, I surround all that with
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.
Work almost like
rotate. Again, you can't define a scale center, so you have to handle it yourself.
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 ...
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
Also, a canvas element default display is
"inline", which is rarely what you want.
Finally, let's dynamically change the values returned by
getRotation to have a little animation.
Here's what changed :
- Add CSS to make the canvas full-page and grey
- Increment a variable
ievery frame and passed it to
- Add some maths to
- 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
See ya !