auroranil
auroranil

Reputation: 2661

Rotate square on its axis in HTML5 Canvas?

I want to create a function that rotates a square on its axis.

var halfWidth = canvas.width/2;
var halfHeight = canvas.height/2;

var x = halfWidth-10;
var y = halfHeight-10;
var w = 20;
var h = 20;
var deg = 45;

rotate(x, y, w, h, deg);

ctx.fillRect(x, y, w, h);

The function:

function rotate(x, y, w, h, deg) {
    // ctx.translate() and ctx.rotate()
    // goes here.
}

How to do this?

Upvotes: 4

Views: 13806

Answers (5)

H. Théo
H. Théo

Reputation: 1

Here's an another solution if you want to draw multiple square

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");


function rd(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min)
}


for (let i = 0; i < 10; i++) {
    drawRect(rd(0, 400), rd(0, 400))
}


function drawRotatedRect(x, y, width, height, degrees) {
    // first save the untranslated/unrotated context
    ctx.save();

    ctx.beginPath();
    // move the rotation point to the center of the rect
    ctx.translate(x + width / degrees, y + height / degrees);
    // rotate the rect
    ctx.rotate(degrees * Math.PI / 180);

    // draw the rect on the transformed context
    ctx.rect(-width / 2, -height / 2, width, height);

    ctx.fillStyle = "gold";
    ctx.fill();

    // restore the context to its untranslated/unrotated state
    ctx.restore();
}

function drawRect(x, y) {
  const squareSize = 50;
  const degrees = 60;

  // draw an unrotated reference rect
  ctx.beginPath();
  ctx.rect(x - squareSize/2, y - squareSize/2 , squareSize, squareSize);
  ctx.fillStyle = "blue";
  ctx.fill();

  // draw a rotated rect
  drawRotatedRect(x, y, squareSize, squareSize, degrees);

  // draw center coord reference point
  drawDot(x, y, 5)
}

function drawDot(x, y, size) {
  ctx.beginPath();
  ctx.arc(x , y, size, 0, 2 * Math.PI);
  ctx.fillStyle = 'black'
  ctx.fill();
}
canvas {
    border:1px solid red;
}
<canvas id="canvas" width=400 height=400></canvas>

Upvotes: 0

Diriector_Doc
Diriector_Doc

Reputation: 610

If you don't want to deal with ctx.save() and all that, there's a brief way to calculate where each new point of the rotated square should be.

The following will draw a green square, and then draw a red square that has been rotated 22.5°.

const ctx = document.querySelector("canvas").getContext("2d");

ctx.fillStyle = "green";
ctx.fillRect(50, 50, 50, 50)

/**
 * 
 * @returns {[number, number]} (x3, y3)
 */
function f(x1, y1, x2, y2, degrees) {
    const rad = degrees * Math.PI / 180;
    return [
        (x2 - x1) * Math.cos(rad) + x1 - (y2 - y1) * Math.sin(rad),
        (x2 - x1) * Math.sin(rad) + y1 + (y2 - y1) * Math.cos(rad)
    ]
}

ctx.fillStyle = "red";
const centre = 75;
/*
 * The centre of the square is at (75, 75)
 * The corner points are at:
 * (50, 50)
 * (100, 50)
 * (100, 100)
 * (50, 100)
 */

ctx.beginPath();
let [newX, newY] = f(centre, centre, 50, 50, 22.5);
ctx.moveTo(newX, newY);

[newX, newY] = f(centre, centre, 100, 50, 22.5);
ctx.lineTo(newX, newY);

[newX, newY] = f(centre, centre, 100, 100, 22.5);
ctx.lineTo(newX, newY);

[newX, newY] = f(centre, centre, 50, 100, 22.5);
ctx.lineTo(newX, newY);

[newX, newY] = f(centre, centre, 50, 50, 22.5);
ctx.lineTo(newX, newY);

ctx.fill();
<canvas width=200 height=200 style="background:gray"></canvas>

I put this graphic together thinking it might help visualize what's going on.

Example of a square rotated

Upvotes: 1

Alex
Alex

Reputation: 457

here is my opinion:

JAVASCRIPT

var canvas = document.getElementById("myCanvas");
var ctx2 = canvas.getContext("2d");
ctx2.fillStyle='#333';

ctx2.fillRect(50,50,100,100);
var ctx = canvas.getContext("2d");


ctx.fillStyle='red';

var deg = Math.PI/180;

ctx.save();
    ctx.translate(100, 100);
    ctx.rotate(45 * deg);
    ctx.fillRect(-50,-50,100,100);
ctx.restore();

ctx2 is the old position and ctx is the new position of the shape. You have to translate the shape with the same x,y coordinates according to where you want position your shape. Then you have to enter values to ctx.fillRect(x,y,w,h);keep x and y as the -ve values (half of height and width to keep it on the diagonal to the canvas otherwise change to manipulate it). and h, w as your desired values.

DMEO

Upvotes: 0

auroranil
auroranil

Reputation: 2661

Thanks dr.dredel for the link.

var cx = canvas.width/2;
var cy = canvas.height/2;

var x = -10;
var y = -10;
var w = 20;
var h = 20;
var deg = 45;

ctx.save();

ctx.translate(cx, cy);
ctx.rotate(deg * Math.PI/180);

ctx.fillRect(x, y, w, h);

ctx.restore();

Explanation:

  • ctx.save() saves the current state of the coordinate system.

  • ctx.translate(cx, cy) changes the origin to the center of canvas

  • ctx.rotate(deg * Math.PI/180) rotates the square to 45 degrees (Note that the parameter is in radians, not degrees)

  • ctx.fillRect( x, y, w, h ) draws the square

  • ctx.restore() restores the last state of the coordinate system.

JS Fiddle link.

Another JS Fiddle link, with a HTML5 slider.

Upvotes: 6

Jani Hartikainen
Jani Hartikainen

Reputation: 43263

If I remember correctly the translation involved was something like first translate to the center point of the rectangle, then rotate wanted amount, then draw. Or possibly first rotate, then translate, I'm a bit rusty =)

Upvotes: 0

Related Questions