首页 > 解决方案 > 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!

标签: javascriptcanvasrotationdraggable

解决方案


通过更多的调查、反复试验和运气,找到了它!已经更新了小提琴 - http://jsfiddle.net/jamesinealing/3chy076x/ - 但对于那些发现自己有同样问题的人来说,这是重要的代码!关键在于将其分解,以便任何水平或垂直鼠标移动实际上都会导致旋转图像上成比例的 x 和 y 偏移,该偏移根据角度而变化(因此 90 度角意味着 x 鼠标移动被平移100% 进入 y 图像移动等)

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();

推荐阅读