Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I rotate a single object on an html 5 canvas?

People also ask

How do you rotate shapes in canvas?

To rotate a shape around its own center, you must first translate the canvas to the center of the shape, then rotate the canvas, then translate the canvas back to 0,0, and then draw the shape. This example first translates (moves) the center of the canvas to the center of the square (cx, cy).

How do you rotate a rectangle in canvas?

Rotating a shape around its center To do this, the following steps are applied to the matrix: First, translate() moves the matrix's origin to the shape's center. rotate() rotates the matrix by the desired amount. Finally, translate() moves the matrix's origin back to its starting point.


I ran into the same problem in a recent project (where I kicked rotating aliens all over the place). I just used this humble function that does the same thing and can be used the same way as ctx.rotate but can be passed an angle. Works fine for me.

function drawImageRot(img,x,y,width,height,deg){
    // Store the current context state (i.e. rotation, translation etc..)
    ctx.save()

    //Convert degrees to radian 
    var rad = deg * Math.PI / 180;

    //Set the origin to the center of the image
    ctx.translate(x + width / 2, y + height / 2);

    //Rotate the canvas around the origin
    ctx.rotate(rad);

    //draw the image    
    ctx.drawImage(img,width / 2 * (-1),height / 2 * (-1),width,height);

    // Restore canvas state as saved from above
    ctx.restore();
}

Yay, my first answer!


Unfortunately in the HTML5 canvas element you can't rotate individual elements.

Animation works like drawing in MS Paint: You draw something, make a screen.. use the eraser to remove some stuff, draw something differently, make a screen.. Draw something else on top, make a screen.. etc etc.

If you have an existing item on the canvas - you'll have to erase it ( use ctx.fillRect() or clearRect() for example ), and then draw the rotated object.

If you're not sure how to rotate it while drawing in the first place:

ctx.save();
ctx.rotate(0.17);
// draw your object
ctx.restore();

To rotate a individual object you have to set the transformation matrix. This is really simple:

            var context = document.getElementById('pageCanvas').getContext('2d');
            var angle = 0;
            function convertToRadians(degree) {
                return degree*(Math.PI/180);
            }
            
            function incrementAngle() {
                angle++;
                if(angle > 360) {
                    angle = 0;
                }
            }
            
            function drawRandomlyColoredRectangle() {  
                // clear the drawing surface
                context.clearRect(0,0,1280,720);
                // you can also stroke a rect, the operations need to happen in order 
                incrementAngle();
                context.save();                
                context.lineWidth = 10;  
                context.translate(200,200);
                context.rotate(convertToRadians(angle));
                // set the fill style
                context.fillStyle = '#'+Math.floor(Math.random()*16777215).toString(16);
                context.fillRect(-25,-25,50,50);
                context.strokeRect(-25,-25,50,50);                
                context.restore();
            }
            
            // Ideally use getAnimationFrame but for simplicity:
            setInterval(drawRandomlyColoredRectangle, 20);
        <canvas width="1280" height="720" id="pageCanvas">
            You do not have a canvas enabled browser
        </canvas>

Basically, to make an object rotate properly without having other shape rotating around, you need to:

  1. save the context: ctx.save()
  2. move the pivot point to the desired location: ctx.translate(200, 200);
  3. rotate: context.rotate(45 * Math.PI / 180);
  4. draw the shape, sprite, whatever: ctx.draw...
  5. reset the pivot: ctx.translate(-200, -200);
  6. restore the context to its original state: ctx.restore();

function spinDrawing() {
    ctx.save();
    ctx.translate(200, 200);
    context.rotate(45 * Math.PI / 180);
    ctx.draw //your drawing function
    ctx.translate(-200, -200);
    ctx.restore();
}

Caveats: After you translating , the origin of the canvas changed, which means when you drawing the shape, the coordinate of the shape should be aligned accordingly.

Shapes drawn outside the list mentioned above won´t be affected. I hope it helps.


This html/javascript code might shed some light on the matter:

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="233" height="233" style="border:1px solid #d3d3d3;">
your browser does not support the canvas tag </canvas>

<script type="text/javascript">

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var canvasWidth=233;
var canvasHeight=233;
var rectWidth=100;
var rectHeight=150;
var x=30;
var y=30;
var translateX= x+(rectWidth/2);
var translateY= y+(rectHeight/2);

ctx.fillRect(x,y,rectWidth,rectHeight);

ctx.translate(translateX,translateY);
ctx.rotate(5*Math.PI/64); /* just a random rotate number */
ctx.translate(-translateX,-translateY); 
ctx.fillRect(x,y,rectWidth,rectHeight);


</script>

</body>
</html>

I find it helpful to see the math related to rotating, I hope this was helpful to you too.


<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="500" height="450" style="border:1px solid #d3d3d3;">
</canvas>

<Button id = "right" onclick = "rotateRight()">Right</option>
<Button id = "left" onclick = "rotateLeft()">Left</option>
<script src = "zoom.js">

</script>

<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

createRect();

function rotateRight()
{
 ctx.save();
 ctx.clearRect(0,0,500,450);
 ctx.translate(c.width/2,c.height/2);
 ctx.rotate(10*Math.PI/180 );  
 ctx.translate(-c.width/2,-c.height/2);
 createRect();

}

function rotateLeft()
{
 ctx.save();
 ctx.clearRect(0,0,500,450);
 ctx.translate(c.width/2,c.height/2);
 ctx.rotate(-10*Math.PI/180 );  
 ctx.translate(-c.width/2,-c.height/2);
 createRect();  
}



function createRect()
{
 ctx.beginPath();
 ctx.fillStyle = "#AAAA00";
 ctx.fillRect(250,250,90,50);
}
</script>

</body>
</html>