HTML5 canvas - part 2: State
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 togetPositions
andgetRotation
- Add some maths to
getPositions
andgetRotation
- 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 !