Нажмите "Холст" на три пикселя.

Я потратил целый день, пытаясь получить щелчок по моему холсту, чтобы вернуть смещение пикселя xy. Какая была миссия!

Вот что я получил:

<!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/

Он создает белый холст в толстой черной рамке.

Нажмите на холст и отобразите координаты XY.

Как вы можете видеть, я намеренно создаю холст, который требует прокрутки, и не выравнивается слева. Это необходимо для создания надежного решения. (Можно ли улучшить тестовый вариант?)

Это очень работает! Но если вы попытаетесь щелкнуть в левом верхнем углу, вы получите (1,2).

Он должен быть (0,0).

Что происходит не так?

РЕДАКТИРОВАТЬ: получить положение мыши относительно области содержимого элемента - этот вопрос имеет отличный ответ (вместе с живым примером), который по-прежнему демонстрирует ту же проблему смещения.

Как получить координаты щелчка мыши на элементе canvas? < - этот вопрос безнадежно загроможден.

http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html < - также демонстрирует то же поведение.

Получение позиции курсора в холсте без jQuery < - использует document.documentElement, что может быть альтернативой искажению с помощью поля CSS/границы/дополнения (?)

EDIT: Теперь это 2,2 не 2,1! Это непоследовательно! ARGH! Я сделал фото с камеры: enter image description here

EDIT: На Firefox я получаю 0.75, 1.91667... enter image description here

EDIT 15Apr: Две попытки здесь:
http://jsfiddle.net/Skz8g/47/
http://jsbin.com/taceso/1/

Ответ 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='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>