Search code examples
javascripthtmlcanvas

Rotating around an arbitrary point: HTML5 Canvas


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>

Solution

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