19

Come see the amazing disappearing rectangle!

But seriously I have a really simple HTML5 canvas that just draws a rectangle(using lineTo instead of rect for a reason).

My Problem: I am attempting to rotate the rectangle 90 degrees. The rectangle should be rotated 90 degrees but instead it disappears.

In my webapp project I am getting weird x,y placement errors when I rotate my complex polygons in HTML5 canvas', so I have created this simple HTML to test rotation & ensure its rotating around its x,y point of 100,100. But even this has weird results when I attempt to rotate a shape.

Can anyone tell me how to get my rectangle visible & how I can rotate my polygons around a specific point without them completely changing x,y values.

Has anyone experienced this issue with HTML5 canvas' & know solutions to fix this?

<canvas id="testCanvas" width="900px" height="900px" style="background-color: blue;">

</canvas>
<script type="text/javascript">

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

    dc.clearRect(0, 0, canvas.width, canvas.height);

    dc.save();
    dc.fillStyle = "#FF0000";

    dc.rotate( 90*Math.PI/180 );  // rotate 90 degrees
    dc.beginPath();
    dc.moveTo(100, 100);
    dc.lineTo(200, 100);
    dc.lineTo(200,300);
    dc.lineTo(100,300);
    dc.closePath();
    dc.fill();

    dc.restore();
-->
</script>
1

3 Answers 3

37

To rotate around a point you need to do 3 steps.

  • First translate the context to the center you wish to rotate around.
  • Then do the actual rotation.
  • Then translate the context back.

Like this:

var canvas = document.getElementById("testCanvas");
var dc     = canvas.getContext("2d");
var angle = 0;
window.setInterval(function(){
    angle = (angle + 1) % 360;
    dc.clearRect(0, 0, canvas.width, canvas.height);

    dc.save();
    dc.fillStyle = "#FF0000";

    dc.translate(150,200); // First translate the context to the center you wish to rotate around.
    dc.rotate( angle*Math.PI/180 ); // Then do the actual rotation.
    dc.translate(-150,-200); // Then translate the context back.

    dc.beginPath();
    dc.moveTo(100, 100);
    dc.lineTo(200, 100);
    dc.lineTo(200,300);
    dc.lineTo(100,300);
    dc.closePath();
    dc.fill();

    dc.restore();
}, 5);
3
  • 2
    I edited the answer with a method that doesn't draw relative to the new center.
    – david
    Commented Jan 20, 2012 at 5:18
  • 1
    Wouldn't it make sense to change angle = angle+1; to angle = (angle + 1) % 360; This helps to avoid the inevitable maxint, even if that number is really large. Commented Feb 9, 2013 at 7:36
  • do the translate x & y parameters have connection to canvas size? Commented Oct 9, 2021 at 21:18
5

When you rotate the canvas, it rotates from the origin (0, 0), so your rectangle ends up getting rotated off the screen.

See this example where it's only rotated 45 deg: http://jsfiddle.net/wjLSm/

One way to fix this is to translate the canvas by its width & height/2: http://jsfiddle.net/wjLSm/1/ (then 0,0 is at the middle -- be aware of this)

2
  • thanks that got it showing on screen but its not rotating around the x,y point of 100,100. The rectangle after rotation has a x,y pos of 200,600. Is there a way to make it rotate around a specific point(100,100)?
    – sazr
    Commented Jan 20, 2012 at 5:11
  • @sazr sure: use ctx.transpose(100,100) anmd then rotate
    – Zibri
    Commented Jan 14, 2023 at 2:15
-1

Did you mean like this?

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

dc.clearRect(0, 0, canvas.width, canvas.height);
dc.save();
dc.fillStyle = "#FF0000";
dc.translate(200, -100);
dc.rotate(45 * Math.PI / 180);
dc.beginPath();
dc.moveTo(100, 100);
dc.lineTo(200, 100);
dc.lineTo(200, 300);
dc.lineTo(100, 300);
dc.closePath();
dc.fill();

// rotate 90 degrees

dc.restore();
<canvas id="testCanvas" width="900px" height="900px" style="background-color: blue;">

</canvas>

Not the answer you're looking for? Browse other questions tagged or ask your own question.