Какой самый простой способ добавить обработчик события щелчка к элементу холста, который будет возвращать координаты x и y клика (относительно элемента холста)?

Не требуется совместимость с устаревшими браузерами, Safari, Opera и Firefox подойдут.

Изменить 2018: свойства не работал для IE. Единственное, что нужно сделать, это заменить на clientX и clientY работают во всех текущих браузерах. Возможно, вы захотите проверить ответ Патрика на более простое, более свежее решение.

Оригинальный ответ:
Как описано в статье, которую я нашел тогда, но больше не существует:

var x;
var y;
if (e.pageX || e.pageY) { 
  x = e.pageX;
  y = e.pageY;
}
else { 
  x = e.clientX   document.body.scrollLeft   document.documentElement.scrollLeft; 
  y = e.clientY   document.body.scrollTop   document.documentElement.scrollTop; 
} 
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;

Для меня все работало отлично. Вместо этого следует использовать

делает его очень чистым. (5 / 5/16): ответ на вопросы патрика , так как это проще и надежнее.


Так как холст не всегда стилизован относительно всей страницы, canvas.offsetLeft/Top не всегда возвращает то, что вам нужно. Он вернет количество пикселей, на которые он смещен, относительно его элемента offsetParent, который может быть чем-то вроде div элемент, содержащий холст с position: relative. Чтобы учесть это, вам нужно пройтись по цепочке offsetParent s, начиная с самого элемента canvas. Этот код отлично работает для меня, протестирован в Firefox и Safari, но должен работать для всех.

function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX  = currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY  = currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;

Последняя строка упрощает получение координат мыши относительно элемента canvas. Все, что нужно для получения полезных координат, это

coords = canvas.relMouseCoords(event);
canvasX = coords.x;
canvasY = coords.y;

Если вам нравится простота, но вы все еще хотите использовать кросс-браузерную функциональность, я обнаружил, что это решение работает лучше всего для меня. Это упрощение решения @ Aldekein, но Без jQuery Глядя на вывод

function getCursorPosition(canvas, event) {
    var rect = canvas.getBoundingClientRect();
    var x = event.clientX - rect.left;
    var y = event.clientY - rect.top;
    console.log("x: "   x   " y: "   y);
}

Современный браузер теперь справится с этим для вас. Chrome, IE9 и Firefox поддерживают смещение X / Y следующим образом, передавая событие из обработчика щелчков.

function getRelativeCoords(event) {
    return { x: event.offsetX, y: event.offsetY };
}

Большинство современных браузеров также поддерживают layerX / Y, однако Chrome и IE используют layerX / Y для абсолютного смещения клика на странице, включая поля, отступы и т. Д. В Firefox , layerX / Y и offsetX / Y эквивалентны, но смещение ранее не существовало. Итак, для совместимости с чуть более старыми браузерами, вы можете использовать:

function getRelativeCoords(event) {
    return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}

Согласно свежему Quirksmode обработчик clientX и clientY методы поддерживаются во всех основных браузерах. Итак, вот и все — хороший рабочий код, который работает в элементе прокрутки на странице с полосами прокрутки:

function getCursorPosition(canvas, event) {
var x, y;

canoffset = $(canvas).offset();
x = event.clientX   document.body.scrollLeft   document.documentElement.scrollLeft - Math.floor(canoffset.left);
y = event.clientY   document.body.scrollTop   document.documentElement.scrollTop - Math.floor(canoffset.top)   1;

return [x,y];
}

Это также требует jQuery для $(canvas).offset() Глядя на вывод

Я сделал полную демонстрацию, которая работает в каждом браузере с полным исходным кодом решения этой проблемы: Эквивалент jQuery document.createElement? . Чтобы попробовать демо, скопируйте код и вставьте его в текстовый редактор. Затем сохраните его как example.html и, наконец, откройте файл в браузере.

Вот небольшая модификация ответа Райана Артеконы или используя

 HTMLCanvasElement.prototype.relMouseCoords = function (event) {
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do {
        totalOffsetX  = currentElement.offsetLeft;
        totalOffsetY  = currentElement.offsetTop;
    }
    while (currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    // Fix for variable canvas width
    canvasX = Math.round( canvasX * (this.width / this.offsetWidth) );
    canvasY = Math.round( canvasY * (this.height / this.offsetHeight) );

    return {x:canvasX, y:canvasY}
}

Будьте осторожны при выполнении преобразования координат ;, в событии щелчка возвращаются несколько значений, не относящихся к браузеру. Использование только clientX и clientY недостаточно, если прокручивается окно браузера (проверено в Firefox 3.5 и Chrome 3.0).

Этот причудливый режим article предоставляет более правильную функцию, которая может использовать pageX или pageY или комбинацию clientX с document.body.scrollLeft и clientY с document.body.scrollTop для вычисления координаты щелчка относительно источника документа.

ОБНОВЛЕНИЕ: Кроме того, offsetLeft и offsetTop относятся к дополнительному размеру элемента, а не к внутреннему размеру. Холст с примененным padding: style не будет отображать верхний левый угол своей области содержимого как offsetLeft. Существуют различные решения этой проблемы ;, простейшим из которых может быть очистка всех стилей рамок, отступов и т. Д. На самом холсте и применение их к блоку, содержащему холст.

Я не уверен, какой смысл всех этих ответов в том, что проходит через родительские элементы и выполняет все виды методов странные вещи Глядя на вывод

Переменная HTMLElement.getBoundingClientRect, предназначенных для обработки фактической позиции экрана любого элемента. Это включает в себя прокрутку, поэтому такие вещи, как scrollTop не нужны:

(из MDN) количество выполненной прокрутки в области области просмотра (или любого другого прокручиваемого элемента ) учетная запись при вычислении ограничивающего прямоугольника

Normal image

Переменная очень простой подход был уже размещен здесь. Это правильно, если без диких CSS правил.

Вы можете создать его с помощью: —

Когда пиксель изображения ширина не соответствует ширине CSS, вам нужно применить некоторое отношение к значениям пикселей:

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Recalculate mouse offsets to relative offsets
  x = event.clientX - left;
  y = event.clientY - top;
  //Also recalculate offsets of canvas is stretched
  var width = right - left;
  //I use this to reduce number of calculations for images that have normal size 
  if(this.width!=width) {
    var height = bottom - top;
    //changes coordinates by ratio
    x = x*(this.width/width);
    y = y*(this.height/height);
  } 
  //Return as an array
  return [x,y];
}

Пока у холста нет границы, это работает для растянутых изображений (jsFiddle) Глядя на вывод

Обработка границ CSS

Если у холста толстая граница, все становится немного сложнее . Вам буквально нужно вычесть границу из ограничивающего прямоугольника. Это можно сделать с помощью . getComputedStyle . Эта ответ описывает процесс Глядя на вывод

функция затем немного подрастает:

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Subtract border size
  // Get computed style
  var styling=getComputedStyle(this,null);
  // Turn the border widths in integers
  var topBorder=parseInt(styling.getPropertyValue('border-top-width'),10);
  var rightBorder=parseInt(styling.getPropertyValue('border-right-width'),10);
  var bottomBorder=parseInt(styling.getPropertyValue('border-bottom-width'),10);
  var leftBorder=parseInt(styling.getPropertyValue('border-left-width'),10);
  //Subtract border from rectangle
  left =leftBorder;
  right-=rightBorder;
  top =topBorder;
  bottom-=bottomBorder;
  //Proceed as usual
  ...
}

Я не могу думать ни о чем, что могло бы запутать эту последнюю функцию. *} JsFiddle Если вам не нравится изменять нативные Глядя на вывод

Оператор Notes

файлы, просто измените функцию и вызовите ее с помощью prototype. Вот очень хороший учебник — (canvas, event), не считая високосных секунд. this. Это как окно, которое вы можете открыть с помощью canvas).

http://www.html5canvastutorials.com. / advanced / html5-canvas-mouse-координаты /

надеюсь, это поможет!

 <canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  function writeMessage(canvas, message) {
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.font = '18pt Calibri';
    context.fillStyle = 'black';
    context.fillText(message, 10, 25);
  }
  function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
  }
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  canvas.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    var message = 'Mouse position: '   mousePos.x   ','   mousePos.y;
    writeMessage(canvas, message);
  }, false);

Использование jQuery в 2016 году для получения координат клика относительно холста, Я делаю:

Это работает, поскольку и canvas offset (), и jqEvent.pageX / Y относятся к документу независимо от положения прокрутки.

$(canvas).click(function(jqEvent) {
    var coords = {
        x: jqEvent.pageX - $(canvas).offset().left,
        y: jqEvent.pageY - $(canvas).offset().top
    };
});

. Чтобы получить их, вы также должны

Обратите внимание, что если ваш холст масштабируется, то эти координаты не совпадают с холстом Доступны некоторые параметры формата даты для выбора даты. . Чтобы получить их, вы должны http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html do:

var logicalCoords = {
    x: coords.x * (canvas.width / $(canvas).width()),
    y: coords.y * (canvas.height / $(canvas).height())
}

Я рекомендую эту ссылку — В Prototype использовать cumulativeOffset () для рекурсивного Суммирование как упомянуто Райаном Artecona выше.

<style type="text/css">

  #canvas{background-color: #000;}

</style>

<script type="text/javascript">

  document.addEventListener("DOMContentLoaded", init, false);

  function init()
  {
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousedown", getPosition, false);
  }

  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;

    alert("x: "   x   "  y: "   y);
  }

</script>

типа «text»)

var canvas = yourCanvasElement;
var mouseX = (event.clientX - (canvas.offsetLeft - canvas.scrollLeft)) - 2;
var mouseY = (event.clientY - (canvas.offsetTop - canvas.scrollTop)) - 2;

См. Демонстрацию в

http://jsbin.com/ApuJOSA/1/edit?html,output . Так что это простая, но немного более сложная тема, чем кажется.

  function mousePositionOnCanvas(e) {
      var el=e.target, c=el;
      var scaleX = c.width/c.offsetWidth || 1;
      var scaleY = c.height/c.offsetHeight || 1;

      if (!isNaN(e.offsetX)) 
          return { x:e.offsetX*scaleX, y:e.offsetY*scaleY };

      var x=e.pageX, y=e.pageY;
      do {
        x -= el.offsetLeft;
        y -= el.offsetTop;
        el = el.offsetParent;
      } while (el);
      return { x: x*scaleX, y: y*scaleY };
  }

Во-первых, здесь обычно возникают спорные вопросы

. Во-первых, здесь обычно возникают спорные вопросы

  1. Как получить элемент относительно координат мыши

  2. Как получить координаты пиксельной мыши Canvas для 2D Canvas API или WebGL

, так что ответы

Как получить элемент относительно координат мыши

Является ли элемент холстом, получая элемент относительно координат мыши, одинаково для всех элементов. Секция

Есть два простых ответа на вопрос «Как получить относительные координаты мыши для холста»

Простой ответ # 1 use offsetX и offsetY

canvas.addEventListner('mousemove', (e) => {
  const x = e.offsetX;
  const y = e.offsetY;
});

Этот ответ работает в Chrome, Firefox и Safari. В отличие от всех других значений событий offsetX и offsetY учитывает преобразования CSS.

Самая большая проблема с offsetX и offsetY заключается в том, что по состоянию на 2019/05 год они не существуют на сенсорных событиях и поэтому не могут использоваться с iOS Safari. Они существуют в событиях указателя, которые существуют в Chrome и Firefox, но не в Safari, хотя , очевидно, Safari работает над этим Глядя на вывод

. Другая проблема заключается в том, что события должны быть на самом холсте. Если вы поместите их в какой-то другой элемент или окно, вы не сможете позже выбрать холст для Ваша точка отсчета.

Простой ответ # 2 используйте clientX, clientY и canvas.getBoundingClientRect

Если вам не нужны преобразования CSS следующий простейший ответ — вызвать canvas. getBoundingClientRect() и вычесть левую из clientX и top из clientY Вот мой глобальный модуль, который я использую —

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
});

. Это будет работать до тех пор, пока нет CSS-преобразований. Он также работает с сенсорными событиями и будет работать с Safari iOS

canvas.addEventListener('touchmove', (e) => {
  const rect = canvas. getBoundingClientRect();
  const x = e.touches[0].clientX - rect.left;
  const y = e.touches[0].clientY - rect.top;
});

Как получить пиксельные координаты мыши для 2D Canvas API

Лучше всего определить, будет ли текст соответствовать прямо перед отображением элемент. Таким образом, вы можете использовать эту функцию, которая не требует, чтобы элемент был на экране.

2 — это число цифр, до которого мы хотим округлить это число. canvas.getBoundingClientRect и clientX и clientY

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const elementRelativeX = e.clientX - rect.left;
  const elementRelativeY = e.clientY - rect.top;
  const canvasRelativeX = elementRelativeX * canvas.width / rect.width;
  const canvasRelativeY = elementRelativeY * canvas.height / rect.height;
});

или offsetX и offsetY

canvas.addEventListener('mousemove', (e) => {
  const elementRelativeX = e.offsetX;
  const elementRelativeX = e.offsetY;
  const canvasRelativeX = elementRelativeX * canvas.width / canvas.clientWidth;
  const canvasRelativeY = elementRelativeX * canvas.height / canvas.clientHeight;
});

Примечание: Это не имеет непосредственного отношения, но я пришел сюда в поисках единственного элемента для объединения вложенных объектов, таких как

Рабочий пример с использованием event.offsetX, event.offsetY

[...document.querySelectorAll('canvas')].forEach((canvas) => {
  const ctx = canvas.getContext('2d');
  ctx.canvas.width  = ctx.canvas.clientWidth;
  ctx.canvas.height = ctx.canvas.clientHeight;
  let count = 0;

  function draw(e, radius = 1) {
    const pos = {
      x: e.offsetX * canvas.width  / canvas.clientWidth,
      y: e.offsetY * canvas.height / canvas.clientHeight,
    };
    document.querySelector('#debug').textContent = count;
    ctx.beginPath();
    ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);
    ctx.fillStyle = hsl((count   % 100) / 100, 1, 0.5);
    ctx.fill();
  }

  function preventDefault(e) {
    e.preventDefault();
  }

  if (window.PointerEvent) {
    canvas.addEventListener('pointermove', (e) => {
      draw(e, Math.max(Math.max(e.width, e.height) / 2, 1));
    });
    canvas.addEventListener('touchstart', preventDefault, {passive: false});
    canvas.addEventListener('touchmove', preventDefault, {passive: false});
  } else {
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mousedown', preventDefault);
  }
});

function hsl(h, s, l) {
  return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
}
.scene {
  width: 200px;
  height: 200px;
  perspective: 600px;
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  animation-duration: 16s;
  animation-name: rotate;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes rotate {
  from { transform: translateZ(-100px) rotateX(  0deg) rotateY(  0deg); }
  to   { transform: translateZ(-100px) rotateX(360deg) rotateY(720deg); }
}

.cube__face {
  position: absolute;
  width: 200px;
  height: 200px;
  display: block;
}

.cube__face--front  { background: rgba(255, 0, 0, 0.2); transform: rotateY(  0deg) translateZ(100px); }
.cube__face--right  { background: rgba(0, 255, 0, 0.2); transform: rotateY( 90deg) translateZ(100px); }
.cube__face--back   { background: rgba(0, 0, 255, 0.2); transform: rotateY(180deg) translateZ(100px); }
.cube__face--left   { background: rgba(255, 255, 0, 0.2); transform: rotateY(-90deg) translateZ(100px); }
.cube__face--top    { background: rgba(0, 255, 255, 0.2); transform: rotateX( 90deg) translateZ(100px); }
.cube__face--bottom { background: rgba(255, 0, 255, 0.2); transform: rotateX(-90deg) translateZ(100px); }
<div class="scene">
  <div class="cube">
    <canvas class="cube__face cube__face--front"></canvas>
    <canvas class="cube__face cube__face--back"></canvas>
    <canvas class="cube__face cube__face--right"></canvas>
    <canvas class="cube__face cube__face--left"></canvas>
    <canvas class="cube__face cube__face--top"></canvas>
    <canvas class="cube__face cube__face--bottom"></canvas>
  </div>
</div>
<pre id="debug"></pre>

Рабочий пример с использованием canvas.getBoundingClientRect и event.clientX и event.clientY

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
ctx.canvas.width  = ctx.canvas.clientWidth;
ctx.canvas.height = ctx.canvas.clientHeight;
let count = 0;

function draw(e, radius = 1) {
  const rect = canvas.getBoundingClientRect();
  const pos = {
    x: (e.clientX - rect.left) * canvas.width  / canvas.clientWidth,
    y: (e.clientY - rect.top) * canvas.height / canvas.clientHeight,
  };
  ctx.beginPath();
  ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2);
  ctx.fillStyle = hsl((count   % 100) / 100, 1, 0.5);
  ctx.fill();
}

function preventDefault(e) {
  e.preventDefault();
}

if (window.PointerEvent) {
  canvas.addEventListener('pointermove', (e) => {
    draw(e, Math.max(Math.max(e.width, e.height) / 2, 1));
  });
  canvas.addEventListener('touchstart', preventDefault, {passive: false});
  canvas.addEventListener('touchmove', preventDefault, {passive: false});
} else {
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mousedown', preventDefault);
}

function hsl(h, s, l) {
  return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
}
canvas { background: #FED; }
<canvas width="400" height="100" style="width: 300px; height: 200px"></canvas>
<div>canvas deliberately has differnt CSS size vs drawingbuffer size</div>

Эй, это в dojo, просто потому что это то, что у меня был код уже для проекта.

Должно быть достаточно очевидно, как преобразовать его обратно в не-додзё ванильный JavaScript.

  function onMouseClick(e) {
      var x = e.clientX;
      var y = e.clientY;
  }
  var canvas = dojo.byId(canvasId);
  dojo.connect(canvas,"click",onMouseClick);

Есть несколько примеров для

Вот некоторые модификации вышеупомянутого решения Райана Артеконы.

function myGetPxStyle(e,p)
{
    var r=window.getComputedStyle?window.getComputedStyle(e,null)[p]:"";
    return parseFloat(r);
}

function myGetClick=function(ev)
{
    // {x:ev.layerX,y:ev.layerY} doesn't work when zooming with mac chrome 27
    // {x:ev.clientX,y:ev.clientY} not supported by mac firefox 21
    // document.body.scrollLeft and document.body.scrollTop seem required when scrolling on iPad
    // html is not an offsetParent of body but can have non null offsetX or offsetY (case of wordpress 3.5.1 admin pages for instance)
    // html.offsetX and html.offsetY don't work with mac firefox 21

    var offsetX=0,offsetY=0,e=this,x,y;
    var htmls=document.getElementsByTagName("html"),html=(htmls?htmls[0]:0);

    do
    {
        offsetX =e.offsetLeft-e.scrollLeft;
        offsetY =e.offsetTop-e.scrollTop;
    } while (e=e.offsetParent);

    if (html)
    {
        offsetX =myGetPxStyle(html,"marginLeft");
        offsetY =myGetPxStyle(html,"marginTop");
    }

    x=ev.pageX-offsetX-document.body.scrollLeft;
    y=ev.pageY-offsetY-document.body.scrollTop;
    return {x:x,y:y};
}

Во-первых, как уже говорили другие, вам нужна функция, чтобы получить позицию элемента canvas . Вот метод, который немного более элегантен, чем некоторые другие на этой странице (ИМХО). Вы можете передать элемент любым и получить его позицию в документе:

function findPos(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft  = obj.offsetLeft;
            curtop  = obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

Теперь вычислите текущую позицию курсора относительно этого:

$('#canvas').mousemove(function(e) {
    var pos = findPos(this);
    var x = e.pageX - pos.x;
    var y = e.pageY - pos.y;
    var coordinateDisplay = "x="   x   ", y="   y;
    writeCoordinateDisplay(coordinateDisplay);
});

Обратите внимание, что я отделил универсальный findPos пользовательских данных ( также можно записать в виде . Мы должны стараться, чтобы наши функции выполнялись по одной задаче.)

Значения узла offsetLeft и offsetTop jQuery-File- Загрузите offsetParent, который может быть какой-то оберткой div (или чего-либо еще, в этом отношении). Когда нет элемента, обертывающего canvas, они относятся к body, поэтому нет смещения для вычитания. Вот почему нам нужно определить положение холста, прежде чем мы сможем сделать что-то еще.

Аналогично, e.pageX и e.pageY задает положение курсора относительно документа. Вот почему мы вычитаем смещение холста из этих значений, чтобы получить истинную позицию.

Альтернативой для позиционированных элементов является непосредственное использование значений e.layerX и e.layerY. Это менее надежно, чем описанный выше метод, по двум причинам:

  1. Эти значения также относятся ко всему документу, когда событие не происходит внутри позиционированного элемента
  2. Они не являются частью какого-либо стандарта

ThreeJS r77 {* } Вы не можете сделать это — браузер не позволит этого из соображений безопасности.

var x = event.offsetX == undefined ? event.layerX : event.offsetX;
var y = event.offsetY == undefined ? event.layerY : event.offsetY;

mouse2D.x = ( x / renderer.domElement.width ) * 2 - 1;
mouse2D.y = - ( y / renderer.domElement.height ) * 2   1;

После попытки многих решений. Это сработало для меня. Может помочь кому-то еще, следовательно, размещения. Получил это от говорится, что

Y Вы не можете определить, отключен ли у пользователя JavaScript (на стороне сервера или на клиенте). Вместо этого вы предполагаете, что javascript отключен, и создаете свою веб-страницу с отключенным javascript. Это избавляет от необходимости

function click(event) {
    const bound = event.target.getBoundingClientRect();

    const xMult = bound.width / can.width;
    const yMult = bound.height / can.height;

    return {
        x: Math.floor(event.offsetX / xMult),
        y: Math.floor(event.offsetY / yMult),
    };
}

Я создавал приложение, имеющее canvas поверх PDF, которое включало много размеров холста, таких как Увеличение и уменьшение pdf, и, в свою очередь, при каждом увеличении / уменьшении PDF I Мне пришлось изменить размер холста, чтобы адаптировать размер PDF, я просмотрел много ответов в stackOverflow и не нашел идеального решения, которое в конечном итоге решит проблему.

Обновление прототипа rxjs и angular 6, и не нашли ответа, относящегося к самой новой версии.

Вот весь фрагмент кода, который будет полезен любому, кто использует rxjs для рисования поверх холста.

  private captureEvents(canvasEl: HTMLCanvasElement) {

    this.drawingSubscription = fromEvent(canvasEl, 'mousedown')
      .pipe(
        switchMap((e: any) => {

          return fromEvent(canvasEl, 'mousemove')
            .pipe(
              takeUntil(fromEvent(canvasEl, 'mouseup').do((event: WheelEvent) => {
                const prevPos = {
                  x: null,
                  y: null
                };
              })),

              takeUntil(fromEvent(canvasEl, 'mouseleave')),
              pairwise()
            )
        })
      )
      .subscribe((res: [MouseEvent, MouseEvent]) => {
        const rect = this.cx.canvas.getBoundingClientRect();
        const prevPos = {
          x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };
        const currentPos = {
          x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };

        this.coordinatesArray[this.file.current_slide - 1].push(prevPos);
        this.drawOnCanvas(prevPos, currentPos);
      });
  }

А вот фрагмент, который исправляет координаты мыши относительно размера холста, независимо от того, как вы увеличиваете / уменьшаете холст.

const prevPos = {
  x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};
const currentPos = {
  x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};

защищено пользователем 456814 15 апреля ’14 в 16:36

Спасибо за ваш интерес к этому вопросу. Поскольку он привлек низкокачественные или спам-ответы, которые пришлось удалить, публикация ответа теперь требует 10 репутация это работает, все, что вам нужно: бонус ассоциации не учитывается ).

Вы хотите ответить на один из этих вопросы без ответа вместо этого?