Let’s write an algorithm in JavaScript to rotate a square by an angle around its center, repeat the high
school program. We will use the Math
class for calculations, and Canvas for displaying the results.
Development of thought, volumetric model: Spinning cube in space.
We calculate the coordinates of the new point using the formulas of the rotation matrix for
two-dimensional space. We rotate the point t
relative to the point t0
— we get the point t'
.
The origin of the coordinates is in the upper left corner, the coordinate axes are directed to the right and
down. The central point for rotations t0
is located in the center of the figure. A square is an array of
four points-vertices. We bypass the array of points, rotate each of them by an angle, then link the points
with lines and draw lines on the canvas. We renew the image at a frequency of 20 frames per second.
<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
<p>Canvas for displaying computations results</p>
</canvas>
'use strict';
let canvas = document.getElementById('canvas');
// original array of points-vertices of square
let square = [{x:50,y:50},{x:50,y:250},{x:250,y:250},{x:250,y:50}];
// figure center, we'll perform a rotation around it
let t0 = {x:150, y:150};
// rotation angle in degrees
let deg = 1;
// figure rotation and image refresh
function repaint() {
// rotate the original array of points by an angle
for (let i = 0; i < square.length; i++)
square[i] = rotateOnDegree(t0, square[i], deg);
// draw the current array of points
drawFigure(canvas, square);
}
// rotate the point (t) by an angle (deg) relative to the point (t0)
function rotateOnDegree(t0, t, deg) {
let t_new = {};
// convert angle of rotation from degrees to radians
let rad = (Math.PI / 180) * deg;
// calculate the coordinates of the new point using the formula
t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.y-t0.y)*Math.sin(rad);
t_new.y = t0.y+(t.x-t0.x)*Math.sin(rad)+(t.y-t0.y)*Math.cos(rad);
// return new point
return t_new;
}
// draw a figure by points from an array
function drawFigure(canvas, arr) {
let context = canvas.getContext('2d');
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// bypass the array of points and link them with lines
context.beginPath();
for (let i = 0; i < arr.length; i++)
if (i == 0)
context.moveTo(arr[i].x, arr[i].y);
else
context.lineTo(arr[i].x, arr[i].y);
context.closePath();
// draw lines on the canvas
context.lineWidth = 2.2;
context.strokeStyle = '#222';
context.stroke();
}
// after loading the page, set the image refresh rate at 20 Hz
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));
Let’s add one more point, which we’ll rotate backwards. The point is distant from the center of the figure by a quarter of the length of the side of the square. let’s shift the center of the square to this point — shift the array of its vertices. We will rotate the square itself clockwise, and its central point — counterclockwise. This code works in conjunction with the previous one.
<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
<p>Canvas for displaying computations results</p>
</canvas>
'use strict';
let canvas2 = document.getElementById('canvas2');
// current array of points
let square2 = [];
// spinning point
let t2 = {x:100, y:100};
// figure rotation and image refresh
function repaint2() {
// rotate the point in the opposite direction
t2 = rotateOnDegree(t0, t2, -deg);
// bypass the points of the original array and shift
for (let i = 0; i < square.length; i++) {
// current point
square2[i] = {};
// shifting the point of the original array
square2[i].x = square[i].x - t0.x + t2.x;
square2[i].y = square[i].y - t0.y + t2.y;
}
// draw the current array of points
drawFigure(canvas2, square2);
}
// after loading the page, set the image refresh rate at 20 Hz
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));
© Golovin G.G., Code with comments, translation from Russian, 2023