Получение местоположения мыши на холсте

Есть ли способ поместить указатель местоположения внутри тега <canvas>? Мне нужно расположение относительно правого верхнего угла <canvas>, а не всей страницы.


person Sam Lee    schedule 11.07.2009    source источник


Ответы (9)


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

Это легко сделать, если вам нужно поддерживать только определенные браузеры, но между f.ex есть различия. Opera и Firefox.

Что-то вроде этого должно работать для этих двоих:

function mouseMove(e)
{
    var mouseX, mouseY;

    if(e.offsetX) {
        mouseX = e.offsetX;
        mouseY = e.offsetY;
    }
    else if(e.layerX) {
        mouseX = e.layerX;
        mouseY = e.layerY;
    }

    /* do something with mouseX/mouseY */
}
person Jani Hartikainen    schedule 11.07.2009
comment
Я настоятельно рекомендую использовать JQuery или другую структуру javascript, которая стандартизирует смещения. - person Soviut; 14.07.2009
comment
Это сработало для меня только в том случае, если я установил относительную позицию холста, как предложил Нат. - person Richard Garside; 09.08.2010
comment
@Richard - Это потому, что layerX и layerY относятся к всему документу для непозиционированных элементов. См. Мой ответ здесь для получения дополнительной информации: stackoverflow.com/questions / 5085689 / - person Wayne; 27.12.2011
comment
Если e.offsetX определен, но равен 0, то этот код делает неправильную вещь. - person prideout; 09.02.2013

Принятый ответ не будет работать каждый раз. Если вы не используете относительное положение, атрибуты offsetX и offsetY могут вводить в заблуждение.

Вы должны использовать функцию: canvas.getBoundingClientRect() из Canvas API.

  function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
  }
  canvas.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
  }, false);
person AxFab    schedule 27.09.2013
comment
это должен быть принятый ответ - person Antonin Cezard; 16.09.2016

Также обратите внимание, что вам понадобится CSS:

положение: относительное;

установите в свой тег холста, чтобы получить относительное положение мыши внутри холста.

И смещение меняется, если есть граница

person Nat    schedule 18.07.2010
comment
рыскал в Интернете, чтобы выяснить, почему Firefox (7) сообщает о странном значении для layerY - это исправлено, большое спасибо! - person Mikey; 06.11.2011
comment
Спасибо! Это была моя проблема. - person garg; 06.01.2012
comment
Спасибо, до этого я получал разные значения. - person Neelam; 11.01.2012
comment
+1 Это устранило проблему смещения 5-10 пикселей, которая была у меня в FF 11. Спасибо! - person Mike Moore; 25.04.2012
comment
Это не единственный или необходимый способ сделать это. Этот ответ должен объяснить, что e.layerX и e.layerY относятся к холсту, когда это позиционированный элемент, и относительно всего документа, когда это не так. Обратите внимание, что эти свойства не являются частью какого-либо стандарта. Есть способы сделать это лучше. - person Wayne; 05.01.2014

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

// Creates an object with x and y defined,
// set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky,
// we have to worry about padding and borders
// takes an event and a reference to the canvas
function getMouse = function(e, canvas) {
  var element = canvas, offsetX = 0, offsetY = 0, mx, my;

  // Compute the total offset. It's possible to cache this if you want
  if (element.offsetParent !== undefined) {
    do {
      offsetX += element.offsetLeft;
      offsetY += element.offsetTop;
    } while ((element = element.offsetParent));
  }

  // Add padding and border style widths to offset
  // Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
  // This part is not strictly necessary, it depends on your styling
  offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
  offsetY += stylePaddingTop + styleBorderTop + htmlTop;

  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;

  // We return a simple javascript object with x and y defined
  return {x: mx, y: my};
}

Вы заметите, что я использую некоторые (необязательные) переменные, которые не определены в функции. Они есть:

  stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0;
  stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0;
  styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0;
  styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0;
  // Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
  // They will mess up mouse coordinates and this fixes that
  var html = document.body.parentNode;
  htmlTop = html.offsetTop;
  htmlLeft = html.offsetLeft;

Я бы рекомендовал вычислить их только один раз, поэтому их нет в функции getMouse.

person Simon Sarris    schedule 04.05.2012
comment
замечательный небольшой служебный метод. Я думаю, что в большинстве случаев вам не нужно каждый раз вычислять смещения холста. - person uchamp; 19.02.2015

Для положения мыши я обычно использую jQuery, поскольку он нормализует некоторые атрибуты события.

function getPosition(e) {

    //this section is from http://www.quirksmode.org/js/events_properties.html
    var targ;
    if (!e)
        e = window.event;
    if (e.target)
        targ = e.target;
    else if (e.srcElement)
        targ = e.srcElement;
    if (targ.nodeType == 3) // defeat Safari bug
        targ = targ.parentNode;

    // jQuery normalizes the pageX and pageY
    // pageX,Y are the mouse positions relative to the document
    // offset() returns the position of the element relative to the document
    var x = e.pageX - $(targ).offset().left;
    var y = e.pageY - $(targ).offset().top;

    return {"x": x, "y": y};
};

// now just make sure you use this with jQuery
// obviously you can use other events other than click
$(elm).click(function(event) {
    // jQuery would normalize the event
    position = getPosition(event);
    //now you can use the x and y positions
    alert("X: " + position.x + " Y: " + position.y);
});

У меня это работает во всех браузерах.

РЕДАКТИРОВАТЬ:

Я скопировал код из одного из моих классов, который использовал, поэтому вызов jQuery для this.canvas был неправильным. Обновленная функция определяет, какой элемент DOM (targ) вызвал событие, а затем использует смещение этого элемента для определения правильной позиции.

person miki725    schedule 01.07.2011

GEE - бесконечно полезная библиотека для устранения проблем с холстом, в том числе расположение мыши.

person Collin    schedule 06.10.2011
comment
Эта библиотека была отличной, спасибо за ссылку. - person justanotherhobbyist; 10.07.2012
comment
Разработчики больше не поддерживают GEE и называют его полностью устаревшим. - person b1nary.atr0phy; 09.10.2012

Простой подход с использованием событий мыши и свойств холста:

Демонстрация функциональности JSFiddle http://jsfiddle.net/Dwqy7/5/
(Примечание: границы не учитываются, что приводит к обособлению):

  1. Добавьте событие мыши на свой холст
    canvas.addEventListener("mousemove", mouseMoved);

  2. Отрегулируйте event.clientX и event.clientY на основе:
    canvas.offsetLeft
    window.pageXOffset
    window.pageYOffset
    canvas.offsetTop
    Таким образом:

    canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset); canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);

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

0,0 вверху слева:

function mouseMoved(event){
    var canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
    var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}

0,0 вверху справа:

function mouseMoved(event){
    var canvasMouseX =  canvas.width - (event.clientX - canvas.offsetLeft)- window.pageXOffset;
    var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
person Keving    schedule 31.05.2014
comment
Отступ на 1 пиксель - это ваша граница в 1 пиксель (границы и отступы учитываются). Вы также должны учитывать прокрутку ... Ура! :-) - person markE; 01.06.2014
comment
@markE Спасибо за внимание; Я скорректировал код выше и в JSFiddle, чтобы учесть прокрутку. Я не мог найти способ отрегулировать границу холста. - person Keving; 01.06.2014

Я бы использовал jQuery.

$(document).ready(function() {

    $("#canvas_id").bind( "mousedown", function(e){ canvasClick(e); } );

}

function canvasClick( e ){

    var x = e.offsetX;
    var y = e.offsetY;

}

Таким образом, ваш холст может быть в любом месте вашей страницы, относительном или абсолютном.

person Joeri    schedule 14.04.2013

Вычтите смещения X и Y элемента DOM холста из положения мыши, чтобы получить локальное положение внутри холста.

person Soviut    schedule 11.07.2009
comment
Как получить X и Y элемента холста dom таким образом, чтобы это работало во всех браузерах? - person Richard Garside; 09.08.2010
comment
Всегда приятно видеть, что кто-то с 18 тысячами репутации раздает чуши советы ... - person b1nary.atr0phy; 09.10.2012
comment
Не могли бы вы сказать мне, почему мой совет вздор? Как вы думаете, он неверный, недостаточно подробный и т. Д.? Это было бы намного полезнее. Кроме того, моя репутация не обязательно означает, что мои ответы будут идеальными, поэтому существует система голосования. Не согласен? Затем проголосуйте против. - person Soviut; 10.10.2012
comment
я проголосовал против. это только похоже на ответ. Нет. - person GameAlchemist; 08.11.2012
comment
Не могли бы вы объяснить, что я должен добавить к ответу, чтобы он стал лучше? Я согласен, что это довольно общий вопрос и, возможно, нужен пример кода и т. Д. Но пока что люди просто сказали нехороший ответ. - person Soviut; 09.11.2012
comment
Вы можете добавить, как получить позицию (x, y) из элемента DOM. - person Ramy Al Zuhouri; 10.10.2013