Получаване на местоположението на мишката в платно

Има ли начин да получите местоположението на мишката в таг <canvas>? Искам местоположението спрямо горния десен ъгъл на <canvas>, а не цялата страница.


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


Отговори (9)


Най-лесният начин вероятно е да добавите слушател на събития onmousemove към елемента canvas и след това можете да получите координатите спрямо платното от самото събитие.

Това е тривиално за постигане, ако трябва да поддържате само определени браузъри, но има разлики между 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
Това работи за мен само ако задам позицията на платното да бъде относителна, както е предложено от Nat. - 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() от API на canvas.

  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) отчиташе странна стойност за слоя Y - това го поправи, много благодаря! - 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

Ще споделя най-бронирания код за мишка, който съм създал досега. Работи във всички браузъри с всякакъв вид подложки, маржове, граници и добавки (като горната лента на stumbleupon)

// 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);

Първоначалният въпрос поиска координати от горния десен ъгъл (втора функция). Тези функции ще трябва да бъдат в обхват, където имат достъп до елемента canvas.

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 на елемента canvas dom по начин, който работи във всички браузъри? - person Richard Garside; 09.08.2010
comment
Винаги е хубаво да видиш някой с 18 000 представителя да раздава много съвети... - 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