DEV Community

Cover image for The Mystery of Rotate Method in HTML Canvas
Kaho Shibuya
Kaho Shibuya

Posted on

The Mystery of Rotate Method in HTML Canvas

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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), it rotates like the image below.
    Alt Text
    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
    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

  5. ctx.fillText(num.toString(), 0, 0); shows the number, which is 1 this time.
    Alt Text
    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);
    }
    


    Alt Text 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

  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

  8. ctx.rotate(-ang) rotates the entire canvas 30 degrees couter-clockwise. It comes back to the original position.
    Alt Text

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)