Just a simple square like this: CanvasRenderingContext2D.rect()
I want the square to rotate, any angle, and obviously keep the same dimensions. I will draw multiple squares on the canvas (from 0 to 100 ), so I don't think transforming/rotating the canvas will do, since each sqaure has its own angle. Is there a good way to do this?
CodePudding user response:
There's nothing stopping you from
- saving the context's state
- modifying the transformation matrix (here with
translate
androtate
andscale
) - drawing a rectangle
- and restoring the state afterwards.
Note how the fillRect
call doesn't need to care about the position and rotation at all.
const canvas = document.getElementById("c");
const ctx = canvas.getContext("2d");
let hue = 0;
for(let y = 0; y < 10; y ) {
for(let x = 0; x < 10; x ) {
ctx.save();
ctx.translate(50 x * 30, 50 y * 30);
ctx.rotate(x y);
ctx.scale(0.1 x / 10, 0.1 y / 10);
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
ctx.fillRect(-10, -10, 20, 20);
ctx.restore();
hue = 10;
}
}
<canvas id="c" width="500" height="500"></canvas>
CodePudding user response:
I got distracted creating this so it took a little longer than expected. So, just for fun here's 100 animated rotating squares...
const numSquares = 100;
class Square {
static canvasWidth = 0;
static canvasHeight = 0;
constructor(canvas, color) {
// Initialize to random values
this.angle = Math.floor(Math.random() * 90);
this.size = Math.floor(Math.random() * 50) 10
this.x = Math.floor(Math.random() * canvas.width);
this.y = Math.floor(Math.random() * canvas.height);
this.color = `rgb(${color},${color},${color})`;
this.xStep = Math.floor(Math.random() * 10) - 5;
this.yStep = Math.floor(Math.random() * 10) - 5;
this.rotStep = Math.floor(Math.random() * 10) - 5;
Square.canvasWidth = canvas.width;
Square.canvasHeight = canvas.height;
}
render(ctx) {
// Draw
ctx.fillStyle = this.color;
ctx.translate(Math.round(this.x), Math.round(this.y));
ctx.rotate(this.angle * (Math.PI / 180));
ctx.fillRect(-this.size / 2, -this.size / 2, this.size, this.size);
ctx.resetTransform();
// Update animation values for next render
this.x = this.xStep;
this.y = this.yStep;
this.angle = (this.angle this.rotStep) % 360;
this.checkOffScreen();
}
// Change direction if heading off-screen
checkOffScreen() {
if (this.x < 0 || this.x > Square.canvasWidth) this.xStep *= -1;
if (this.y < 0 || this.y > Square.canvasHeight) this.yStep *= -1;
}
}
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const squares = [];
let color = 0;
const colorStep = 256 / numSquares;
// Create the squares
for (let i = 0; i < numSquares; i ) {
squares.push(new Square(canvas, Math.round(color)));
color = colorStep;
}
// Render loop
const render = () => {
ctx.fillStyle = "red";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (const sq of squares) {
sq.render(ctx);
}
window.requestAnimationFrame(render);
};
window.requestAnimationFrame(render);
<canvas id="canvas" width="500" height="500"></canvas>