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.
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 */
}
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);
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
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
.
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.
Mince est une bibliothèque sans cesse utile pour lisser les problèmes avec canvas, y compris l'emplacement de la souris.
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):
Ajouter un événement de souris à votre toile
canvas.addEventListener("mousemove", mouseMoved);
-
Ajuster
event.clientX
etevent.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);
}
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.
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.