10
\$\begingroup\$

I want to rotate single sprites on the canvas without rotating the whole canvas.

I also don't want to create a new canvas for each object I have.

Also, it would be interesting to know which solution is then the most performant.

\$\endgroup\$

3 Answers 3

14
\$\begingroup\$

It’s important to note that changing the co-ordinate system with rotate and translate do not affect anything that’s currently drawn into the canvas. It only affects subsequent drawing actions.

var TO_RADIANS = Math.PI/180; 
function drawRotatedImage(image, x, y, angle)
{ 
    // save the current co-ordinate system 
    // before we screw with it
    context.save(); 

    // move to the middle of where we want to draw our image
    context.translate(x, y);

    // rotate around that point, converting our 
    // angle from degrees to radians 
    context.rotate(angle * TO_RADIANS);

    // draw it up and to the left by half the width
    // and height of the image 
    context.drawImage(image, -(image.width/2), -(image.height/2));

    // and restore the co-ords to how they were when we began
    context.restore(); 
}

Source: http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/

\$\endgroup\$
0
1
\$\begingroup\$

Based on Luis Estada's answer, I created rotateContext function to rotate images and other shapes:

const TO_RADIANS = Math.PI / 180; 

const rotateContext = (context, origin, angle, callback) => {
    // save the current co-ordinate system 
    context.save();

    // move to the origin of our element
    context.translate(origin.x, origin.y);

    // rotate around that point, converting our 
    // angle from degrees to radians 
    context.rotate(angle * TO_RADIANS);

    // restore context to initial position
    context.translate(-origin.x, -origin.y);

    // draw rotated elements
    callback(context);

    // and restore the coords system
    context.restore(); 
}

// ... more code

// draw rotated image
rotateContext(context, rotation.origin, rotation.angle, () => {
    context.drawImage(this.sprite, 0, 0, 225, 225, position.x, position.y, width, height);
});

// ... or

// draw rotated shape
rotateContext(context, rotation.origin, rotation.angle, () => {
    context.fillStyle = 'green';
    context.fillRect(position.x, position.y, width, height);
});
```
\$\endgroup\$
-2
\$\begingroup\$

Change the context, place your image, then reset the context by multiplying your first number by -1.

example:

    context.rotate(k);
    context.drawImage(img,c,d,e,f,g,h,i,j);
    context.rotate(k * -1)
\$\endgroup\$
1
  • 2
    \$\begingroup\$ There is a lot that can go wrong with this approach. Floating point inaccuracies can occur even in such seemingly trivial cases, which would then keep accumulating with every drawn image. Better use context.save() and context.restore() instead. \$\endgroup\$
    – Philipp
    Commented Feb 23, 2023 at 11:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .