Calculations used to rotate an image on canvas

Asked

Viewed 1,015 times

11

I have the following code below to be able to rotate an image through the canvas.

        function qs(selector) {
            return document.querySelector(selector);
        }

        function rotacionar(canvas, image, angle)
        {
            canvas.height = image.height;
            canvas.width = image.width;

            var context = canvas.getContext('2d');

            context.translate(image.width / 2, image.height / 2);

            context.rotate(angle * Math.PI / 180)

            context.drawImage(image, -image.width / 2, -image.height / 2);

        }

        function onLoad()
        {
            var canvas    = qs('#canvas');
            var image     = qs('#image');
            var btnRotate = qs('#rotate');

            var angle = 0;

            btnRotate.addEventListener('click', function () {
                rotacionar(canvas, image, angle += 90);
            });

        }

        window.addEventListener('load', onLoad)
<img id="image" src="data:image/jpeg;base64,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";">

    
    <canvas id="canvas"></canvas>

    <button id="rotate" style="display:block">
        Rotate
    </button>

My question is about that part:

// A
canvas.height = image.height;

canvas.width = image.width;

var context = canvas.getContext('2d');

// B
context.translate(image.width / 2, image.height / 2);

// C
context.rotate(angle * Math.PI / 180)

// D
context.drawImage(image, -image.width / 2, -image.height / 2);

A) The canvas is defined with the same image dimensions (height and width).

B) The method translate of canvas.getContext('2d') is called in then set the first parameter with the image width divided by 2, and the second, the height divided by 2.

C) is made a conversion of degrees to some other unit that I don’t know what it is. That stretch is the angle * Math.PI / 180. This is the moment that rotate is called.

D) The method drawImage is then called by defining which parameters x and y shall have the image width and height values divided by two and negative respectively.

On the steps listed above:

  • Why in A, canvas needs to have the same image dimensions?
  • Why in B, canvas needs to have the values of translate need to have the geometric measurements of the image divided by 2 (height and width)?

  • This conversion that is done in C, deals with which rotation measure scale to which?

  • Why the method that draws the image in D needs to have the values divided by two and negative?

1 answer

14


Why in A, canvas needs to have the same image dimensions?

This action creates a buffer - a temporary workspace - the same size as the target image.

Why in B, canvas needs to have Translate values need to have image geometric measurements divided by 2 (height and width)?

Because the cursor for the action is, by default, located in [0,0]:

inserir a descrição da imagem aqui

translate() move the cursor to the middle of the image:

inserir a descrição da imagem aqui

This conversion that is done in C, deals with which rotation measure scale to which?

According to the documentation, the angle of rotation is expressed in radians - hence the need for conversion:

180 graus = π radianos

Why the method that draws the image in D needs to have the values divided by two and negative?

Negative values are called offset - the image will be rotated with reference to its medium, but it should be drawn in the original coordinates.

  • 2

    I don’t know if you get the joke, but we have the Math.PI and we have the figure of the parrot :P

Browser other questions tagged

You are not signed in. Login or sign up in order to post.