user1773603
user1773603

Reputation:

border offset with getting mouse coordinates on a canvas

I try to get mouse coordinates on a canvas which has borders defined in CSS. First, I have used a solution found out on this link to get the coordinates of a mouse over a canvas :

 function getPosition(event)
      {
        var x = new Number();
        var y = new Number();
        var canvas = document.getElementById("canvas");

        if (event.x != undefined && event.y != undefined)
        {
          x = event.x;
          y = event.y;
        }
        else // Firefox method to get the position
        {
          x = event.clientX + document.body.scrollLeft +
              document.documentElement.scrollLeft;
          y = event.clientY + document.body.scrollTop +
              document.documentElement.scrollTop;
        }

        x -= canvas.offsetLeft;
        y -= canvas.offsetTop;

      }

solution 1 the result of this method. You can see that coordinates have a shift of 10 pixels, i.e the width of canvas borders.

To fix this issue of border width, I modified like this :

   var computedStyle = window.getComputedStyle(canvas,null);
var topBorder = parseInt(computedStyle.getPropertyValue("border-top-width"),10);
var leftBorder = parseInt(computedStyle.getPropertyValue("border-left-width"),10);

// (x,y) coordinates
x -= canvas.offsetLeft + leftBorder;
y -= canvas.offsetTop + topBorder;

But this doesn't work very well : I have a light shifting on the corners (1 or 2 px shifting) ; you can see the result of this modification on solution 2

I also tried to do :

function getPosition(event) {

    var x, y;
    var rect = canvas.getBoundingClientRect();
    var computedStyle = window.getComputedStyle(canvas,null);
    var topBorder = parseInt(computedStyle.getPropertyValue("border-top-width"),10);
    var leftBorder = parseInt(computedStyle.getPropertyValue("border-left-width"),10);

    var x = event.clientX - rect.left - leftBorder;
    var y = event.clientY - rect.top - topBorder;

    // Display coordinates
    xspan.innerHTML = x;
    yspan.innerHTML = y;

  }

The result is shown on solution 3 and there's still a light shift of 1, 2 pixels for the inner corners of the board.

I would like put the (0,480) mouse coordinates in the inner left bottom of canvas, (0,0) at the inner left up corner, (480,0) at the right up corner and (480,480) in the right bottom corner.

How to deal with the "10 pixel" of borders width (see CSS) ?

I make you notice that, before calling getPosition, I have added 0.5px to all canvas coordinates because, for example, a line drawn at i=1 with border-width equal to 1, must be drawn at x = 0.5.

If anyone could give me advices to get valid coordinates on this canvas taking account of the borders width.

Thanks

Upvotes: 0

Views: 888

Answers (1)

jehna1
jehna1

Reputation: 3130

Borders

Do as @markE said and wrap your <canvas> element inside a div:

<div id="game-wrapper">
  <canvas id="game" width="481" height="481">
</canvas>

And give the border to the game-wrapper div. Also make game-wrapper to be display: inline-block; so the border lays out correctly around the canvas.

Then your whole coordinate script could be this:

function getPosition(event) {
  var x = event.layerX;
  var y = event.layerY;
}

Cursor

Aside from that, i think your real problem is that the cursor's pivot point is not at the tip of the cursor, but rather a couple of pixels away from it (at least in OSX). You can observe this by changing the cursor to crosshair:

cursor: crosshair;

Coordinate system

You also asked about the valid way to do a coordinate system transformation. I've found that it's good to have some function that translates the "in-game" coordinates to actual canvas coordinates and back. In your case the 0.5px line you draw:

function Vector2(x,y) {
  this.x = x;
  this.y = y;
}

Vector2.prototype.toGameCoordinates() {
  return new Vector2(
    this.x - 0.5,
    this.y - 0.5
  );
}

Vector2.prototype.toCanvasCoordinates() {
  return new Vector2(
    this.x + 0.5,
    this.y + 0.5
  );
}

Upvotes: 1

Related Questions