jamesinealing
jamesinealing

Reputation: 592

Handling a rotated canvas image dragable relative to the canvas not the image

I want to allow users to rotate an image in a canvas and then drag it to position it. This is working fine for angles of 0 degrees and 180 degrees but I am having trouble working out the trigonometry to make the image move relative to the canvas, rather than to it's original orientation.

Demo jsfiddle: http://jsfiddle.net/jamesinealing/3chy076x/ (now updated with a fix as described below)

Excerpt:

ctx.rotate(angle * Math.PI / 180);
// this is where a formula is needed to get the correct pan values based on the angle
panXTransformed = panX * Math.cos(angle * Math.PI / 180);
panYTransformed = panY * Math.cos(angle * Math.PI / 180);
ctx.drawImage(pic, panXTransformed, panYTransformed, pic.width, pic.height);

You will see here that if you click in the canvas and drag vertically up and down the image moves towards the 'top' arrow of the image, not following the mouse to the top of the canvas. Try it at other angles and it exhibits a range of behaviours!

I know I need to bring in some factor to manipulate both X and Y with such movement, but I can't for the life of me find anything that works!

Upvotes: 0

Views: 199

Answers (1)

jamesinealing
jamesinealing

Reputation: 592

Through some more investigation, trial and error, and a slice of luck, found it! Have updated the fiddle - http://jsfiddle.net/jamesinealing/3chy076x/ - but here's the important bit of code for anyone who finds themselves with the same problem! The crucial bit was breaking it up so that any horizontal or verticle mouse movement could actually contribute to a proportionate x and y shift on teh rotated image, which varied according to the angle (so a 90-degree angle means an x mouse movement is translated 100% into a y image movement etc)

ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate((canvas.width - pic.width) / 2, (canvas.height - pic.height) / 2); 
ctx.rotate(angle * Math.PI / 180);
// now set the correct pan values based on the angle
panXX = (panX*(Math.cos(angle * Math.PI / 180)));
panXY = (panY*(Math.sin(angle * Math.PI / 180)));
panYY = (panY*(Math.cos(angle * Math.PI / 180)));
panYX = (panX*(Math.sin(angle * Math.PI / 180)));
panXTransformed = panXX+panXY;
panYTransformed = panYY-panYX;
ctx.drawImage(pic, panXTransformed, panYTransformed, pic.width, pic.height);
ctx.fillStyle="#0000FF";
ctx.fillRect(0,0,5,5); // place marker at 0,0 for reference
ctx.fillStyle="#FF0000";
ctx.fillRect(panXTransformed, panYTransformed,5,5); // place marker at current tranform point
ctx.restore();

Upvotes: 1

Related Questions