I've spent the whole day trying to get a click over my canvas to return the pixel xy offset. What a mission this has been!
This is what I've ended up with:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<div id="logX">x</div>
<div id="logY">y</div>
<div style="margin-left:100px">
<div style="margin-left:100px">
<canvas id="myCanvas" width="100" height="1000" style="border:20px solid #000000;"></canvas>
</div>
</div>
<script>
var canvas = document.getElementById('myCanvas');
canvas.addEventListener('click', on_canvas_click, false);
function getNumericStyleProperty(style, prop) {
return parseInt(style.getPropertyValue(prop),10);
}
function on_canvas_click(ev) {
var boundingRect = ev.target.getBoundingClientRect();
var x = ev.clientX - boundingRect.left,
y = ev.clientY - boundingRect.top;
var style = getComputedStyle(canvas, null);
x -= getNumericStyleProperty(style, "margin-left");
y -= getNumericStyleProperty(style, "margin-top");
x -= getNumericStyleProperty(style, "border-left-width");
y -= getNumericStyleProperty(style, "border-top-width");
x -= getNumericStyleProperty(style, "padding-left");
y -= getNumericStyleProperty(style, "padding-top");
$("#logX").text( ev.target.getBoundingClientRect().left
+ ", " + ev.clientX
+ ", " + canvas.offsetLeft
+ ", " + x
);
$("#logY").text( ev.target.getBoundingClientRect().top
+ ", " + ev.clientY
+ ", " + canvas.offsetTop
+ ", " + y
);
}
//$( document ).on( "mousemove", function( event ) {
//$( "#log" ).text( "pageX: " + event.pageX + ", pageY: " + event.pageY );
//});
</script>
</body>
</html>
http://jsbin.com/xajeluxija/2/
It produces a white canvas within a thick black border.
Click within the canvas and it will display the XY coordinates.
As you can see, I'm deliberately creating a canvas that requires scrolling, and is not aligned to the left. This is to force a robust solution. (Can the test case be improved?)
It very nearly works! But if you try clicking in the top left corner you will get (1,2).
It should be (0,0).
What is going wrong?
EDIT: getting mouse position relative to content area of an element -- this question has an excellent answer (together with live example) which still exhibits the same offset problem.
How do I get the coordinates of a mouse click on a canvas element? <-- this question is hopelessly cluttered.
http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html <-- also exhibits the same behaviour.
Getting cursor position in a canvas without jQuery <-- uses document.documentElement
which might be an alternative to faffling with CSS margin/border/padding(?)
EDIT: Now it is 2,2 not 2,1! It is inconsistent! ARGH! I took photos with my camera:
EDIT: On Firefox I get 0.75, 1.91667...
EDIT 15Apr:
Two attempts here:
http://jsfiddle.net/Skz8g/47/
http://jsbin.com/taceso/1/