在画布中单击是三个像素

我花了一整天的时间试图点击我的画布以返回像素 xy 偏移量.这是一项多么艰巨的任务!

这就是我最终得到的结果:

<!DOCTYPE html><html><头><meta charset="utf-8"><title>JS斌</title></头><身体><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><脚本>var canvas = document.getElementById('myCanvas');canvas.addEventListener('click', on_canvas_click, false);函数getNumericStyleProperty(样式,道具){返回 parseInt(style.getPropertyValue(prop),10);}功能 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 );//});</脚本></身体></html>


http://jsbin.com/taceso/1/

解决方案

正如您所发现的,在计算鼠标位置时会计算边框大小.

因此,将您的画布包装在一个容器 div 中,容器 div 的边框为 20px.

如果边框在画布本身上,这将消除所需的额外计算.

注意:我将样式用于#borderDiv &#myCanvas 在页眉的样式部分中.

var canvas = document.getElementById('myCanvas');canvas.addEventListener('click', on_canvas_click, false);var context=canvas.getContext('2d');context.fillStyle='红色';context.fillRect(0,0,10,1);context.fillRect(0,0,1,10);函数getNumericStyleProperty(样式,道具){返回 parseInt(style.getPropertyValue(prop),10);}功能 on_canvas_click(ev) {var boundingRect = ev.target.getBoundingClientRect();var x = ev.clientX - boundingRect.left,y = ev.clientY - boundingRect.top;$("#logX").text("x="+x);$("#logY").text("y="+y);}

#borderDiv{margin:0px;宽度:100 像素;高度:1000px;边框:20px 纯黑色;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></脚本><div id="logX">x</div><div id="logY">y</div><div style="margin-left:100px"><div style="margin-left:100px"><div id='borderDiv'><canvas id="myCanvas" width=100 height=1000 style="cursor:crosshair"></canvas></div></div></div>

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/

解决方案

As you've discovered, border size is counted in calculating mouse position.

So wrap your canvas in a container div with the container div having the 20px border.

This takes away the extra calculations needed if the border were on the canvas itself.

Note: I put the styles for #borderDiv & #myCanvas in a Style section in the Header.

var canvas = document.getElementById('myCanvas');
canvas.addEventListener('click', on_canvas_click, false);

var context=canvas.getContext('2d');

context.fillStyle='red';
context.fillRect(0,0,10,1);
context.fillRect(0,0,1,10);

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;

  $("#logX").text("x="+x);
  $("#logY").text("y="+y);
}

#borderDiv{margin:0px; width:100px; height:1000px; border:20px solid black;}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<div id="logX">x</div>
<div id="logY">y</div>

<div style="margin-left:100px">
  <div style="margin-left:100px">
    <div id='borderDiv'>
      <canvas id="myCanvas" width=100 height=1000 style="cursor:crosshair"></canvas>
    </div>
  </div>
</div>

相关文章