edoreld
edoreld

Reputation: 301

How can I get the "rotated" coordinates of a mouse-click on a canvas?

The background

I have an image editing program that displays a canvas where the user can perform several actions such as drawing shapes. The shapes drawn by an user are sent to a server which then adds them as an element to an XML file. The XML file is sent back to the client. The client then reads this XML file and for each element it draws the corresponding shape.

I want to add new functionality to my program. I want to make it so that an user can rotate the view locally. That is, this user should be able to click on a button which will rotate the canvas 90 degrees to the right. So if a shape is at position (10, 10) of a 40x40 canvas, it will be at (30, 10) upon clicking on this button.

I have achieved this by using rotation and translation as follows:

ctx.translate(width/2,height/2);
ctx.rotate(90*Math.PI/180); 
ctx.translate(-width/2,-height/2);

// draw shapes from returned XML file

So now when shapes are drawn from my XML files, they will appear rotated.

The problem

The problem appears when I try to draw a new shape on the rotated canvas. Let's say I am drawing a rectangle from (10, 10) to (15, 15). The program will send these coordinates to my server. The server will then add them to the XML file and send the XML file back to my client. When my client goes through its drawing cycle, it will draw the new shape. However, since the canvas has been rotated, it will draw at the shape at the rotated position.

So I am drawing from (10, 10) to (15, 15) but the shape I am seeing appear on the canvas goes from (30, 10) to (25, 15).

To deal with this, I had the idea that instead of sending the server the actual coordinates of the mouse, I should feed it the coordinates as if the canvas had been rotated in the opposite direction to the same degree as the rotation created by the rotation button.

So if the degree of rotation is 90 and I click on (10, 10), instead of feeding my program (10, 10) I would feed it (10, 30). That way when drawing it it would rotate it and it would appear in the right place.

Hence my question, how can I get the "rotated" coordinates of a mouse-click on a canvas? (Without any external libraries)

// Code to draw a rectangle
Rectangle.prototype.handleInput = function() {

    var coord = {};
    var anchor = {};
    var imgData = s.ctx.getImageData(0, 0, s.width, s.height);
    var drawingSquare = false;
    var squareDrawn = false;
    var color, thickness;
    var mouseMoved;

    s.canvas.onmousedown = function(e) {
        mouseMoved = false;
        color = getColor();
        thickness = getThickness();
        anchor.x = e.clientX - s.getX();
        anchor.y = e.clientY - s.getY();

        drawingSquare = true;
        imgData = s.ctx.getImageData(0, 0, s.width, s.height);
    };

    s.canvas.onmousemove = function(e) {
        if (drawingSquare) {
            mouseMoved = true;
            coord.x = e.clientX - s.getX();
            coord.y = e.clientY - s.getY();

            s.ctx.putImageData(imgData, 0, 0);
            Rectangle.draw(anchor.x, anchor.y, coord.x, coord.y, color, thickness);
            squareDrawn = true;
            xml.editRect(anchor.x, anchor.y, getColor(), getThickness(), coord.x, coord.y);
        }
    };

    s.canvas.onmouseup = function(e) {
        drawingSquare = false;
// startX, startY, strokeStyle, lineWidth, endX, endY

if (mouseMoved) {
    sm.save();

    xml.addRect(anchor.x, anchor.y, getColor(), getThickness(), coord.x, coord.y);
}

Upvotes: 0

Views: 673

Answers (1)

NetByMatt
NetByMatt

Reputation: 719

If you're only rotating in 90 degree increments then the math is fairly straight forward. This example rotates coordinates 90° to the left.

unrotated.x = anchor.y;
unrotated.y = s.height - anchor.x;

Other rotations are similar, just swapping in and out x and y positions and widths and heights.

Upvotes: 1

Related Questions