Reputation:
I'm trying to rotate an image and move it around the canvas using the arrow keys. The plan is to have the left and right keys control the rotation of the image, and the up-down key control the movement - a bit like a tank!
I can successfully rotate an image around a centre point and place it back where it should be in the canvas, but once I rotate it by, say 45 deg, I would like the up key to move it right, rotate 180 and the up-key moves it down the canvas etc. At the moment, I can rotate the image using left/right keys, but up/down keys are always up/down the canvas.
Do I somehow need to rotate the canvas coordinates by the same amount as the image?
This is what I have so far and is in my draw function…
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(T1.x + base_image.width/2, T1.y + base_image.height/2);
ctx.rotate(rotation * Math.PI/180);
ctx.translate(-(T1.x + base_image.width/2), -(T1.y + base_image.height/2));
ctx.drawImage(base_image, T1.x, T1.y);
ctx.stroke();
ctx.restore()
T1.x
and T1.y
are the x and y coordinates of the image.
Thanks!
Upvotes: 3
Views: 379
Reputation: 54109
The quickest way to draw a rotated, uniformly-scaled image on Edge, Chrome, and Firefox is
// When the image has loaded add the center offsets
image.onload = function(){
// … your code
this.centerX = -this.width/2;
this.centerY = -this.height/2;
}
// When rendering
// x,y position of image center
// scale the uniform scale
// rotate angle in radians starting at 0 and + clockwise
var xdx = Math.cos(rotate) * scale;
var xdy = Math.sin(rotate) * scale;
ctx.setTransform(xdx, xdy, -xdy, xdx, x, y);
ctx.drawImage(image,image.centerX,image.centerY)
The above method with the extra sin and cos and the two multiplications is significantly quicker on Chrome, slightly quicker on Firefox, and I forget the margin on Edge, but it was quicker than the next quickest method:
ctx.setTransform(scale, 0, 0, scale, x, y);
ctx.rotate(rotate);
ctx.drawImage(image, image.centerX, image.centerY);
Though I am leaving the canvas transform state as it is, you can continue using both methods without having to reset the canvas state. When you are done with all the rendering, to restore the current transform, use
ctx.setTransform(1, 0, 0, 1, 0, 0);
To save a tiny bit of time, each time you convert from degrees to radians, create a const DEG2RAD = Math.PI/180;
. Then, you can convert with var radians = degrees*DEG2RAD;
or save by typing const D2R = Math.PI/180;
or call const oneDeg = Math.PI/180;
.
Upvotes: 0
Reputation:
Finally got it! The solution was to separate the rotation and the movement rather than trying to do it all using ctx.translate
.
In my draw function called every 100 Hz:
ctx.save();
ctx.translate(T1.x + base_image.width/2, T1.y + base_image.height/2);
ctx.rotate(rotation*Math.PI/180);
ctx.drawImage(base_image, -base_image.width/2, -base_image.height/2);
ctx.restore();
ctx.stroke();
The left key is, for example, like:
rotation = rotation - 5;
Draw();
The up key is, for example, like:
var radians = (rotation*Math.PI/180)
T1.x += 4*Math.cos(radians);
T1.y += 4*Math.sin(radians);
Draw();
Note: For this to work, I had to change the default orientation of the image in paint by 45 deg.
Upvotes: 3