Reputation: 23379
I'm trying to write some code that allows a user to arbitrarily drag an image around a canvas, resize the image, and rotate the image using their mouse. I am having some trouble with my trigonometry.
All points of interest are relative to the center of the image. In the illustration below the mouse is at the absolute position 850, 400 (relative to the canvas' upper left). Since there is no rotation I can easily figure out that the mouse is in the relative position 250, 0 (relative to the center of the image).
After I rotate the image 270° and put the mouse in the same position, the absolute is 600, 150. The relative position is exactly the same as it was before the rotation though (250, 0).
Given the absolute coordinates of the image's center point, it's rotation, and the absolute position of the mouse, how can I determine the transformed, rotated coordinates of the mouse relative to the center of the image?
I've tried many things and attempted to adapt answers from similar StackOverflow questions. My current attempt uses a Matrix class someone published in a Gist.
layerRelativePoint(x, y, layer){
var radians = layer.rotation * (Math.PI/180);
var matrix = new Matrix();
matrix.translate(-layer.x, -layer.y);
matrix.rotate(radians);
var [x, y] = matrix.transformPoint(x, y);
return {x, y};
}
Demo: https://plnkr.co/edit/T9XCfpZVlMWLMY67bOvW?p=preview
Upvotes: 3
Views: 532
Reputation: 23379
I've found an answer on Math.se.
Here is the implementation I came up with:
/**
* Translate a point's absolute coordinates to it's coordinates
* relative to a possibly rotated center point
* -------------------------------------------------------------
* @param {number} absPointX - The absolute x ordinate of the point to translate
* @param {number} absPointY - The absolute y ordinate of the point to translate
* @param {number} centerX - The absolute x ordinate of the center point of rotation
* @param {number} centerY - The absolute y ordinate of the center point of rotation
* @param {number} rotationDegrees - The angle of rotation in degrees
* @returns {x, y} - The translated point's coordinates
*/
function translatePoint(absPointX, absPointY, centerX, centerY, rotationDegrees=0) {
// Get coordinates relative to center point
absPointX -= centerX;
absPointY -= centerY;
// Convert degrees to radians
var radians = rotationDegrees * (Math.PI / 180);
// Translate rotation
var cos = Math.cos(radians);
var sin = Math.sin(radians);
var x = (absPointX * cos) + (absPointY * sin);
var y = (-absPointX * sin) + (absPointY * cos);
// Round to nearest hundredths place
x = Math.floor(x * 100) / 100;
y = Math.floor(y * 100) / 100;
return {x, y};
}
Upvotes: 1