Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

canvas mouse event position different than cursor

I am starting to experiment with canvas, this might be a basic issue but can not find the problem here.

My mouse cursor is slower than the line I draw on canvas with the mouse event coordinates. What am I missing here?

Fiddle

P.S.- Same problem if using jQuery's mouse event: http://jsfiddle.net/2q4Sd/2/

window.addEvent('mousemove', function (event) {
    draw(event.event.clientX);
});

function draw(mouseX) {
    ctx.beginPath();
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;
    ctx.moveTo(mouseX, 0);
    ctx.lineTo(mouseX, canvas.height);
    ctx.stroke();
    ctx.closePath();
}
like image 439
Rikard Avatar asked Dec 31 '13 12:12

Rikard


2 Answers

Your drawn line is off for two reasons. Both related to the difference between the coordinates returned by event.clientX etc. and those used by the canvas:

  1. Each canvas has it's own coordinate system, which defaults to starting with (0,0) at the upper-left of the canvas element. event.clientX however measures relative to the 'client area' (basically, the viewport, or in the case of an iframe, it's the area that it takes up on a page). Therefore, when you pass event.clientX into your draw() function, and use that to draw to the canvas, you're not taking account of the difference in these two coordinate systems. To do that, you can use something like: .getBoundingClientRect().
  2. The other issue you have is that there can be, and in your case there is, a difference between the scale of the coordinates return by event.clientX etc. and those used by a particular canvas element. I talked about this here: https://stackoverflow.com/a/19079320/1937302 But basically, unless you have a good reason, I'd made sure that the dimensions of the canvas as set by CSS are equal to the dimensions as set using the HTML attributes width and height.

Addressing both of these gives:

http://jsfiddle.net/2q4Sd/8/

Relavent HTML:

<canvas style="width:400px;height:300px;" width="400" height="300"></canvas>

New draw() function:

function draw(mouseX) {

    // fixes offset caused by event.clientX and the canvas element
    // having different origins for their coordinate systems:
    var xCoord = mouseX - canvas.getBoundingClientRect().left;

    ctx.beginPath();
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;
    ctx.moveTo(xCoord, 0);
    ctx.lineTo(xCoord, canvas.height);
    ctx.stroke();
    ctx.closePath();
}
like image 115
Ben Jackson Avatar answered Sep 28 '22 08:09

Ben Jackson


It's because firstly the size isn't set correctly on the canvas so it sized post render via CSS and secondly because you have default padding.

If you change the canvas line to:

<canvas style="width:400px;height:300px;" width="400" height="300"></canvas>

and reset the padding/margin:

* {padding:0px;margin:0px;}

You should be good, otherwise you'll have to deal with offsets by getting the canvas dimensions using something like getBoundingClientRect()

I've updated your fiddle below:

http://jsfiddle.net/2q4Sd/9/

like image 36
Matthew Riches Avatar answered Sep 28 '22 06:09

Matthew Riches