Obtenir l'emplacement de la souris dans canvas

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

43
demandé sur Dagg Nabbit 2009-07-11 23:31:58

9 réponses

Plus Simple est probablement d'ajouter un écouteur d'événement onmousemove à l'élément canvas, et alors vous pouvez obtenir les coordonnées par rapport à la toile de l'événement lui-même.

C'est trivial à accomplir si vous avez seulement besoin 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
répondu Jani Hartikainen 2009-07-11 20:10:47

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);
35
répondu AxFab 2013-09-27 10:18:53

Notez également que vous aurez besoin de CSS:

Position: relative;

Définissez votre balise canvas, afin d'obtenir la position relative de la souris à l'intérieur du canvas.

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

22
répondu Nat 2013-11-23 13:37:20

Je vais partager le code de souris le plus pare-balles que j'ai créé jusqu'à présent. Il fonctionne sur tous les navigateurs avec toutes sortes de rembourrage, de marge, de bordure et d'add-ons (comme la barre supérieure de 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};
}

Vous remarquerez que j'utilise des variables (optionnelles) qui ne sont pas définies dans la fonction. Ils 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
répondu Simon Sarris 2012-05-04 14:25:31

Pour la position de la souris, j'utilise généralement jQuery car il normalise certains 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 était faux. La fonction mise à jour détermine quel élément DOM (targ) a causé l'événement, puis utilise le décalage de cet élément pour déterminer la position correcte.

7
répondu miki725 2011-07-08 06:27:29

Mince est une bibliothèque sans cesse utile pour lisser les problèmes avec canvas, y compris l'emplacement de la souris.

6
répondu Collin 2012-10-09 09:10:36

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

Démonstration de fonctionnalité JSFiddle http://jsfiddle.net/Dwqy7/5/
(Note: les bordures ne sont pas prises en compte, ce qui entraîne un off-by-one):

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

  2. Ajuster event.clientX et event.clientY basé sur:
    canvas.offsetLeft
    window.pageXOffset
    window.pageYOffset
    canvas.offsetTop
    Ainsi:

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

La question initiale demandait des coordonnées dans le coin supérieur droit (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
répondu Keving 2014-05-31 23:08:53

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
répondu Joeri 2013-04-14 16:40:50

Soustrayez les décalages X et Y de l'élément DOM canvas de la position de la souris pour obtenir la position locale à l'intérieur du canvas.

-1
répondu Soviut 2009-07-11 19:37:03