The Mystery of Rotate Method in HTML Canvas

Tags: canvas, html, javascript, w3school
Published: 2021-02-26 06:22:38

Following [this w3school's tutorial](https://www.w3schools.com/graphics/canvas_clock.asp), 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](https://stackoverflow.com/questions/66347245/why-are-multiple-rotate-needed-to-place-every-number-on-the-right-spot-canv/66347497#66347497) (I mean thanks to [Kaiido](https://stackoverflow.com/users/3702797/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"](https://www.w3schools.com/graphics/canvas_clock_numbers.asp) 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.

```javascript
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)

1. `ang` is π/6 radian that is equal to 30 degrees.

2. `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 using `ctx.translate(radius, radius);` (see the final code [here](https://codepen.io/ShivChan/pen/LYbOMYJ)), it rotates like the image below.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkvj0heccg7bw0xhu4jf.png)
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.

3.  `ctx.translate(0, -radius * 0.85);` moves the entire canvas its y-direction.  The value is negative, so it goes up.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/utva9k7wotdg41pt4218.png)
Since the canvas now is rotated 30 degrees, the y-direction looks going diagonal way.

4. `ctx.rotate(-ang)` rotates the entire canvas 30 degrees counter-clockwise.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rjl245fwxunxkpp67p5d.png)

5. `ctx.fillText(num.toString(), 0, 0);` shows the number, which is `1` this time.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2koh8b3zvulbxkit5sb.png)
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.  ```javascript
 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);
  }
``` ![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2i0pb0m1lpktf6ibqa0.png) The number is on the tilt.
Be careful and make sure when to use which method!

6. Again, `ctx.rotate(ang)` rotates the entire canvas 30 degrees clockwise.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/300wug3t648mf9m9buf1.png)

7. `ctx.translate(0, radius * 0.85);` moves the entire canvas its y-direction.  This time, the value is positive, so it goes down.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lsg6xifznf7angsjtuq.png)

8. `ctx.rotate(-ang)` rotates the entire canvas 30 degrees couter-clockwise.  It comes back to the original position.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wagrnj4ctpqjsuhmvycs.png)


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.

{% codepen https://codepen.io/ShivChan/pen/LYbOMYJ %}

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!