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

I'm trying to figure out how to rotate a single object on an html 5 canvas.

For example: http://screencast.com/t/NTQ5M2E3Mzct - I want each one of those cards to be rotated at a different degree.

So far, all I've seen are articles and examples that demonstrate ways to rotate the entire canvas. Right now, I'm guessing I'll have to rotate the canvas, draw an image, and then rotate the canvas back to it's original position before drawing the second image. If that's the case, then just let me know! I just have a feeling that there's another way.

Anyone have any idea?

Thanks in advance!

Answers


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();

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){

    //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);

    //reset the canvas  
    ctx.rotate(rad * ( -1 ) );
    ctx.translate((x + width / 2) * (-1), (y + height / 2) * (-1));
}

Yay, my first answer!


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

<body>
    <canvas width="1280" height="720" id="pageCanvas">
        You do not have a canvas enabled browser
    </canvas>
    <script>
        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);
    </script>
</body>

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();
}

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>

To rotate an object you can use rotate() method. Here the example how to rotate a rectangular object to 135 degrees of clockwise.

 <script>
  var canvas = document.getElementById('Canvas01');
  var ctx = canvas.getContext('2d');

  var rectWidth = 100;
  var rectHeight = 50;

  //create line
  ctx.strokeStyle= '#ccc';
  ctx.beginPath();
  ctx.moveTo(canvas.width / 2, 0);
  ctx.lineTo(canvas.width / 2, canvas.height);
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.moveTo(0, canvas.height/2);
  ctx.lineTo(canvas.width, canvas.height/2);
  ctx.stroke();
  ctx.closePath();

  // translate ctx to center of canvas
  ctx.translate(canvas.width / 2, canvas.height / 2);

  // rotate the rect to 135 degrees of clockwise
  ctx.rotate((Math.PI / 180)*135);

  ctx.fillStyle = 'blue';
  ctx.fillRect(0, 0, rectWidth, rectHeight);
</script>
</body>

Here the demo and you can try yourself: http://okeschool.com/examples/canvas/html5-canvas-rotate


I found this question because I had a bunch of stuff on a canvas, drawn with canvas lines, painstakingly, and then decided some of them should be rotated. Not wanting to do a whole bunch of complex stuff again I wanted to rotate what I had. A simple solution I found was this:

ctx.save();

ctx.translate(x+width_of_item/2,y+height_of_item/2);
ctx.rotate(degrees*(Math.PI/180));
ctx.translate(-(x+width_of_item/2),-(y+height_of_item/2));

// THIS IS THE STUFF YOU WANT ROTATED
// do whatever it is you need to do here, moveto and lineto is all i used 
// I would expect anything to work. use normal grid coordinates as if its a
// normal 0,0 in the top left kind of grid

ctx.stroke();
ctx.restore();

Anyway - it might not be particularly elegant but its a dead easy way to rotate one particular element onto your canvas.

Look at all those rotated elements!


Need Your Help

Cut Corners using CSS

css css3 css-shapes

I'm looking to "cut" the top left corner of a div, like if you had folded the corner of a page down.

Java: Difference in usage between Thread.interrupted() and Thread.isInterrupted()?

java multithreading

Java question: As far as I know, there are two ways to check inside a thread whether the thread received an interrupt signal, Thread.interrupted() and Thread.isInterrupted(), and the only difference