using HTML5 Canvas - rotate image about arbitrary point

44,095

In general, what you want to do is:

  1. Transform the context to the point on the canvas that the object should rotate about.
  2. Rotate the context.
  3. Transform the context by the negative offset within the object for the center of rotation.
  4. Draw the object at 0,0.

In code:

ctx.save();
ctx.translate( canvasRotationCenterX, canvasRotationCenterY );
ctx.rotate( rotationAmountInRadians );
ctx.translate( -objectRotationCenterX, -objectRotationCenterY );
ctx.drawImage( myImageOrCanvas, 0, 0 );
ctx.restore();

Here's a working example showing this in action. (The math for the rotation was just experimentally hacked to find a swing amount and offset in radians that fit the quickly-sketched gauge dial.)

As may be evident, you can substitute the translate call in step #3 above with offsets to the drawImage() call. For example:

ctx.drawImage( myImageOrCanvas, -objectRotationCenterX, -objectRotationCenterY );

Using context translation is recommended when you have multiple objects to draw at the same location.

Share:
44,095
Abhijit
Author by

Abhijit

Software developer and architect Interested in JavaScript, C#, SharePoint, Azure

Updated on November 15, 2020

Comments

  • Abhijit
    Abhijit over 3 years

    Rotate the dial on top of a semi circular(Northern Hemisphere) image as background. range could be 0 - 180 degrees. on input to the method that does canvas transformation, the dial would rotate and stop over the matched value. Here's what I was trying based on help and sample passed on by phrogz

  • Abhijit
    Abhijit over 13 years
    Thanks for quick help and the Demo too. :)
  • Phrogz
    Phrogz over 13 years
    For further discussion, see this (duplicate) question and answer: HTML5 Canvas drawImage at an angle.
  • Abhijit
    Abhijit over 13 years
    Still stuck when it comes to replacing the parameters in rotate() method to incorporate feed from data structure.
  • Phrogz
    Phrogz over 13 years
    @Ab Perhaps you are receiving degrees and passing them to rotate() without first converting them to radians? If so, multiply by Math.PI/180. If that doesn't help, edit your question with a pared-down test case showing your actual code and we can move forward from there.
  • Abhijit
    Abhijit over 13 years
    Many Thanks, I'm almost there :)
  • Wesley
    Wesley about 9 years
    Thanks, been looking to do this for hours now :-)