Rotating a sprite with HTML5 and Canvas

From a newbie’s perspective the process of drawing an image and then rotating it is daunting.

In my simple mind I had expected to be able to simply grab a context to work with (i.e. the HTML image object) and then paint it to the canvas context and apply transformations.

So I started to write the following…

var ctx = document.getElementById(“canvas”).getContext(“2d”);

ctx.drawImage(…with all the spritesheet selection criteria as parameters…);

… and then I stopped. I was suddenley confused at how any further code would be interpreted. How on earth can I write JavaScript to physically rotate the image object supplied to the drawImage() method.

So before I could think of writing a call to the .rotate() method I knew I had to understand how this drawing and transforming worked.

The solution lay here: https://developer.mozilla.org/en/Canvas_tutorial/Transformations

The canvas context within which you work needs to be understood.
To effectively rotate my image on it’s axis I discovered that I needed to first save() the context’s state.
I then needed to translate() it.
Then I could rotate() and finally I would draw the image.

What is important is the sequence of events.

Take a look at the following:
//gl.ctx is the canvas context that I create within the global (gl {}) namespace. // var o = sprite object that carries a spritesheet object.

gl.ctx.save();

gl.ctx.translate(o.x,o.y); gl.ctx.rotate(o.angle * (Math.PI / 180));

gl.ctx.drawImage(o.spritesheet.image, o.frame * o.spritesheet.offsetw, 0, o.w, o.h, -o.w/2, -o.h/2, o.w, o.h);

gl.ctx.restore();

The above sequence of instructions see to it that the rotate() method is effective only for the image that I am about to draw.
The translate method effectively moves the canvas by x and y.

So if I have a sprite that is sat at 128 x 128 on the canvas. To apply my transformation I need to move the canvas 128 pixels to the right and 128 pixels down.

ctx.translate(128,128);


https://developer.mozilla.org/en/Canvas_tutorial/Transformations#Translating
Once I have snapped the canvas to this location (admittedly translate is a lousy method name for a newbie to understand) I am able to consider rotating the image.

My angles are set as increments of 45. So I have 8 possible positions thru 0 to 315 degrees.
So I rotate the image using the .rotate() method (note the important use of Math.PI / 180) and then draw the image.

But there’s one vital thing left to consider.

I have moved the canvas context to be relative to the image that I have just rotated.

The 6th and 7th parameters in drawImage() need to reflect this since they position my sprite to an x and y on the canvas.
You might think therefore that since my sprite is sat at 0 , 0 on the canvas (since the canvas context snapped to the x and y of the sprite) I could just specify 0, 0 here.
But that would give the effect of the sprite spinning around the top left point of the graphic. I don’t want that. I want the sprite to spin on its axis.

So I specify a negative number. The sprite is to be drawn at minus half the width and minus half the height of the sprite.

The “half” bit is vital in pin-pointing the centre of the image.

Effectively I have now drawn the image to less than the top left of the canvas context.
For an image of 32×32 this means that the image is drawn at -16, -16.
This gives the impression of the sprite spinning on its central axis.

Finally once all the work is done I can restore the canvas state so as not to affect any other subsequent drawing.

You can see the final effect here: www.wilfscorner.co.uk/sandpit/1/rotate1.php

This topic requires a good deal of thought and application on my part. I hope to revisit it shortly and offer new thoughts. It’s quite possible that I edit this post to correct terminology or my understanding of the process. But hopefully there is enough pointers here to help somebody through what is a different way of thinking in term of sprite application.

About these ads
Post a comment or leave a trackback: Trackback URL.

Comments

  • Cody  On October 27, 2010 at 7:36 pm

    Your thought processes while learning the canvas element are extremely helpful. I’m still wrapping my head around the save() and restore() methods, but I found this link to be the most useful yet…

    http://html5.litten.com/understanding-save-and-restore-for-the-canvas-context/

  • Anthony C.  On December 20, 2011 at 3:07 am

    Great find! Love this. I have no idea why the API for Canvas implemented rotations of the entire context being the object of rotation. One would think that the context could have a RotateImage() function implemented.

    You have provided a very good alternative to rotating images WITHOUT rotating the entire canvas and all art assets. Thank you for this.

    For clarity, the final fix is to substitute the destinationX and destinationY parameters for ctx.drawImage with a -1*( myImageWidth / 2) and -1*( myImageHeight / 2) followign a rotation call;

  • Thampuran  On August 4, 2013 at 4:40 pm

    I was using ‘click’ eventlistener to get the taped position of canvas and there by getting the relative position of an image object. But while rotating the image, the canvas points getting were wrong…:( I’ve several other objects also in my sceen :(

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: