web-dev-qa-db-fra.com

Obtenir l'emplacement de la souris dans le canevas

Existe-t-il un moyen d'obtenir la souris de localisation dans un <canvas> tag? Je veux l'emplacement par rapport au coin supérieur droit du <canvas>, pas la page entière.

43
Sam Lee

Le moyen le plus simple consiste probablement à ajouter un écouteur d'événement onmousemove à l'élément canvas, puis vous pouvez obtenir les coordonnées relatives au canevas à partir de l'événement lui-même.

C'est trivial à accomplir si vous n'avez besoin que de prendre en charge des navigateurs spécifiques, mais il existe des différences entre f.ex. Opera et Firefox.

Quelque chose comme ça devrait fonctionner pour ces deux:

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 */
}
41
Jani Hartikainen

La réponse acceptée ne fonctionnera pas à chaque fois. Si vous n'utilisez pas la position relative, les attributs offsetX et offsetY peuvent être trompeurs.

Vous devez utiliser la fonction: canvas.getBoundingClientRect() de l'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);
37
AxFab

Notez également que vous aurez besoin de CSS:

position: relative;

mis à votre balise canvas, afin d'obtenir la position relative de la souris à l'intérieur de la toile.

Et le décalage change s'il y a une bordure

22
Nat

Je vais partager le code de souris le plus à l'épreuve des balles que j'ai créé jusqu'à présent. Il fonctionne sur tous les navigateurs avec toutes sortes de rembourrage, marge, bordure et modules complémentaires (comme la barre supérieure de la pierre d'achoppement)

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

Vous remarquerez que j'utilise certaines variables (facultatives) qui ne sont pas définies dans la fonction. Elles sont:

  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;

Je recommande de ne les calculer qu'une seule fois, c'est pourquoi ils ne sont pas dans la fonction getMouse.

16
Simon Sarris

Pour la position de la souris, j'utilise généralement jQuery car il normalise certains des attributs d'événement.

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

Cela fonctionne pour moi dans tous les navigateurs.

MODIFIER:

J'ai copié le code d'une de mes classes que j'utilisais, donc l'appel jQuery à this.canvas avait tort. La fonction mise à jour détermine quel élément DOM (targ) a provoqué l'événement, puis utilise le décalage de cet élément pour déterminer la position correcte.

7
miki725

[~ # ~] gee [~ # ~] est une bibliothèque infiniment utile pour atténuer les problèmes avec le canevas, y compris la souris emplacement.

6
Collin

Approche simple utilisant les propriétés de l'événement et du canevas de la souris:

Démo JSFiddle des fonctionnalités http://jsfiddle.net/Dwqy7/5/
(Remarque: les bordures ne sont pas prises en compte, ce qui entraîne un décalage par un):

  1. Ajoutez un événement de souris à votre toile
    canvas.addEventListener("mousemove", mouseMoved);

  2. Ajustez event.clientX Et event.clientY En fonction de:
    canvas.offsetLeft
    window.pageXOffset
    window.pageYOffset
    canvas.offsetTop
    Donc:

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

La question d'origine demandait des coordonnées en haut à droite (deuxième fonction). Ces fonctions devront être dans une portée où elles peuvent accéder à l'élément canvas.

0,0 en haut à gauche:

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

0,0 en haut à droite:

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

J'utiliserais jQuery.

$(document).ready(function() {

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

}

function canvasClick( e ){

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

}

De cette façon, votre toile peut être n'importe où sur votre page, relative ou absolue.

1
Joeri