Following this w3school's tutorial, I created an analog clock with HTML canvas.
In the process of creating it, I encountered the mystery of canvas and it puzzled me a lot!
However, thanks to Stack Overflow (I mean thanks to Kaiido who answered my question), I think I understand how HTML canvas works.
Now, I share my understanding.
What is the problem?
There are five steps in the tutorial and "Clock Numbers" was the Chinese Wall for me.
In this section, you place each number upright in the right position of the clock.
The function drawNumbers
, the following, makes it happen.
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let radius = canvas.height/2;
ctx.translate(radius, radius);
radius = radius * 0.9;
function drawClock() {
drawFace(ctx, radius);
drawNumbers(ctx, radius);
}
function drawNumbers(ctx, radius) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
for(num = 1; num < 13; num++){
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius * 0.85);
ctx.rotate(-ang);
}
}
In the for-loop in the function, you can see there are a bunch of rotate
methods.
They look like rotating and rotating back several times and it confused me.
Since there was no detailed explanation on w3school's tutorial, I had no clues! (Please add it!)
What's happening in this for loop is...
First, let's see how 1
will be placed and break it down to see what happens on each line of the code. (only inside of for-loop)
ang
is π/6 radian that is equal to 30 degrees.ctx.rotate(ang)
rotates the entire canvas 30 degrees clockwise.
Since the rotation center point is changed from the origin to the center of the clock by usingctx.translate(radius, radius);
(see the final code here), it rotates like the image below.
The yellow square shows the original position while the gray square shows the position at the moment.
Assume the gray one as being on the yellow one and gets rotated 30 degrees.
Plus, the green circle is the rotation center point set as a reference.ctx.translate(0, -radius * 0.85);
moves the entire canvas its y-direction. The value is negative, so it goes up.
Since the canvas now is rotated 30 degrees, the y-direction looks going diagonal way.ctx.rotate(-ang)
rotates the entire canvas 30 degrees counter-clockwise.
-
ctx.fillText(num.toString(), 0, 0);
shows the number, which is1
this time.
The number is upright and positions in the right place.
However, if you "fillText" at the wrong timing, the number would look different. Take a look at the example below.
Assuming you "fillText" before rotating the entire canvas back.
for(num = 1; num < 13; num++){ ang = num * Math.PI / 6; ctx.rotate(ang); ctx.translate(0, -radius * 0.85); ctx.fillText(num.toString(), 0, 0); //"fillText" before rotating back. ctx.rotate(-ang); ctx.rotate(ang); ctx.translate(0, radius * 0.85); ctx.rotate(-ang); }
The number is on the tilt.
Be careful and make sure when to use which method! Again,
ctx.rotate(ang)
rotates the entire canvas 30 degrees clockwise.
ctx.translate(0, radius * 0.85);
moves the entire canvas its y-direction. This time, the value is positive, so it goes down.
ctx.rotate(-ang)
rotates the entire canvas 30 degrees couter-clockwise. It comes back to the original position.
That's all process for one number. After getting back the position to the original, the same thing happens in turn till it gets to number 12.
You cannot actually see how the canvas transforms, so it was hard for me to understand what's going on, especially rotate
method.
This is my understanding and an attempt to visualize the process, so if you notice something wrong here please leave a comment and point them out.
Thank you!
Top comments (0)