Encuentra la posición del mouse relativa al elemento

244

Quiero hacer una pequeña aplicación de pintura usando lienzo. Entonces necesito encontrar la posición del mouse en el lienzo.

Ben Shelock
fuente
2
Solución completa: acko.net/blog/…
edA-qa mort-ora-y
3
Me encanta lo breve, pero explica todo lo que esta publicación es.
dwjohnston
Esto es muy antiguo, pero acabo de comenzar un proyecto de GitHub que, entre otras cosas, hace exactamente lo que necesita: bralessdeveloper.com/mouse-move-interaction-spot-js
Fausto NA

Respuestas:

177

Para las personas que usan JQuery:

A veces, cuando tiene elementos anidados, uno de ellos con el evento adjunto, puede ser confuso comprender lo que su navegador ve como padre. Aquí, puede especificar qué padre.

Toma la posición del mouse y luego la resta de la posición de desplazamiento del elemento principal.

var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;

Si está intentando obtener la posición del mouse en una página dentro de un panel de desplazamiento:

var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();

O la posición relativa a la página:

var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();

Tenga en cuenta la siguiente optimización del rendimiento:

var offset = $('#element').offset();
// Then refer to 
var x = evt.pageX - offset.left;

De esta manera, JQuery no tiene que buscar #elementcada línea.

Actualizar

A continuación, hay una versión más reciente, solo JavaScript, de @anytimecoder a continuación para los navegadores que admiten getBoundingClientRect () .

sparkyspider
fuente
77
Funcionó para ti @ben, agradecería una "Respuesta correcta" o un comentario sobre lo que aún no funciona para ti. Quizás pueda ayudar más.
sparkyspider
8
Debe evitar usar $ ('selector') en un controlador de eventos, a menos que desee un código muy lento. Preseleccione su elemento y use la referencia preseleccionada en su controlador. Lo mismo para $ (ventana) hacer eso una vez y guardarlo en caché.
Austin Francia
2
esto no es una mención necesaria: si va a copiar pegar el código anterior, recuerde que debe corregir var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();avar y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Raj Nathani
77
¿Cómo podría ser esa la respuesta ya que la pregunta no tiene nada que ver con jQuery?
FlorianB
2
@Black pero algunas personas preguntan cosas en javascript en lugar de jquery porque jquery puede no ser compatible en sus entornos.
dbrree
307

Como no encontré una respuesta sin jQuery que pudiera copiar / pegar, aquí está la solución que utilicé:

function clickEvent(e) {
  // e = Mouse click event.
  var rect = e.target.getBoundingClientRect();
  var x = e.clientX - rect.left; //x position within the element.
  var y = e.clientY - rect.top;  //y position within the element.
}

JSFiddle de ejemplo completo

en cualquier momento
fuente
2
Debe redondear el límite delimitador para garantizar valores enteros con este método.
Jake Cobb
2
La nueva edición debería solucionar los problemas de desplazamiento (usando clientX / Y)
Erik Koopmans
66
Esta respuesta debe ser votada. Gracias anytimecoder y @ErikKoopmans.
Ivan
3
PSA: el comentario de @mpen es obsoleto; Este método funciona, incluso en casos de desplazamiento. Ver versión actualizada de su Fiddle: jsfiddle.net/6wcsovp2
Xharlie
44
¡Gracias! Una nota: necesita e.currentTarget, no e.target. De lo contrario, elementos secundarios que afectarán
Maxim Georgievskiy
60

A continuación se calcula la relación de posición del mouse con el elemento del lienzo:

var example = document.getElementById('example'); 
example.onmousemove = function(e) { 
    var x = e.pageX - this.offsetLeft; 
    var y = e.pageY - this.offsetTop; 
}

En este ejemplo, se thisrefiere al exampleelemento y ees el onmousemoveevento.

LindaQ
fuente
83
¿Quizás soy yo pero dos líneas de códigos que usan la palabra clave "this" carecen de contexto?
Deratrius
99
Definitivamente falta de contexto. 'e' es el evento y 'este' es el elemento al que está vinculado el evento var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
Nick Bisby
22
Esto no funciona si algún elemento descendiente usa posicionamiento relativo o absoluto.
edA-qa mort-ora-y
12
Puede cambiar thisa e.currentTarget, eso le dará la posición relativa al elemento al que agregó el detector de eventos.
Linus Unnebäck
2
Esto parece dar la posición relativa a la parte visible del elemento, no a todo el elemento. ¿Hay alguna manera de adaptarse a eso si parte del elemento no se puede ver en la ventana gráfica y hay barras de desplazamiento, etc.?
frabjous
37

No hay respuesta en javascript puro que devuelva coordenadas relativas cuando el elemento de referencia está anidado dentro de otros que pueden estar con posicionamiento absoluto. Aquí hay una solución para este escenario:

function getRelativeCoordinates (event, referenceElement) {

  const position = {
    x: event.pageX,
    y: event.pageY
  };

  const offset = {
    left: referenceElement.offsetLeft,
    top: referenceElement.offsetTop
  };

  let reference = referenceElement.offsetParent;

  while(reference){
    offset.left += reference.offsetLeft;
    offset.top += reference.offsetTop;
    reference = reference.offsetParent;
  }

  return { 
    x: position.x - offset.left,
    y: position.y - offset.top,
  }; 

}
Atrahasis
fuente
3
No creo que tenga en cuenta el htmldesplazamiento del elemento
apieceofbart
3
Funciona muy bien con contenedores de desplazamiento, con solo un pequeño cambio: reemplazar while(reference !== undefined)con while(reference). Al menos en Chrome, el offsetParent no termina siendo undefined, pero null. Solo verificar si referencees verdadero asegurará que funcione con ambos undefinedy null.
blex
Daría otro +1 si pudiera, porque me hizo saber que hay una offsetParentpropiedad, ¡que resulta ser muy útil en otras situaciones!
FonzTech
En general, verificar contra indefinidos suele ser una mala idea
Juan Mendes
Creo que necesitas restar scrollLeft y scrollTopcompensar a los descendientes desplazados.
Robert
20

Una buena reseña de la dificultad de este problema se puede encontrar aquí: http://www.quirksmode.org/js/events_properties.html#position

Usando la técnica que se describe allí, puede encontrar la posición de los ratones en el documento. A continuación, sólo comprobar para ver si está dentro del cuadro delimitador del elemento, que se puede encontrar por llamada element.getBoundingClientRect()que devolverá un objeto con las siguientes propiedades: { bottom, height, left, right, top, width }. A partir de ahí, es trivial averiguar si incluso sucedió dentro de su elemento o no.

David W. Keith
fuente
1
Lamentablemente, esto falla si hay algún tipo de rotación
Eric
17

Probé todas estas soluciones y, debido a mi configuración especial con un contenedor transformado por matriz (biblioteca panzoom), ninguna funcionó. Esto devuelve el valor correcto, incluso si se amplía y se panoramiza:

mouseevent(e) {
 const x = e.offsetX,
       y = e.offsetY
}

Pero solo si no hay elementos secundarios en el camino. Esto se puede evitar al hacerlos 'invisibles' para el evento, usando CSS:

.child {
   pointer-events: none;
}
Fabian von Ellerts
fuente
3
Esta es definitivamente la forma de hacerlo en 2019. Las otras respuestas están cargadas con equipaje viejo y viejo.
Colin D
1
@ColinD gracias! Olvidé agregar que esto también funciona en IE11.
Fabian von Ellerts
Esto funcionó para mí. Sin embargo, sospecho que 1) Pocos votos positivos 2) las respuestas mejor calificadas son mucho más complicadas y 3) No veo explicaciones de inconvenientes. ¿Alguien sabe alguna estafa de usar este enfoque?
Mark E
1
@ MarkE No hay nada sospechoso al respecto. Es una de las muchas fallas de StackOverflow. Esas respuestas que ves en la parte superior se publicaron muchos años antes de esta respuesta aquí, por lo que obtuvieron un gran impulso de voto positivo. Una vez que una respuesta gana impulso, es bastante difícil y bastante raro superarla.
Jack Giffin
9

Me encontré con esta pregunta, pero para que funcione para mi caso (usando dragover en un elemento DOM (no siendo lienzo en mi caso)), descubrí que solo tienes que usar offsetXy offsetYen el evento dragover-mouse .

onDragOver(event){
 var x = event.offsetX;
 var y = event.offsetY;
}
Juan
fuente
2
Esto funciono muy bien para mi. ¿Por qué nadie ha votado esto? Me pregunto si hay dificultades. ¡Si encuentro alguno, informaré!
lubina el
77
event.offsetX es relativo al elemento sobre el que se encuentra actualmente el puntero del mouse, no el elemento que tiene el detector de dragover adjunto. Si no tiene una estructura de elementos anidados, entonces está bien, pero si la tiene, no funcionará.
opsb
7

I +1 'La respuesta de Mark van Wyk, ya que me llevó en la dirección correcta, pero no lo resolvió por mí. Todavía tenía un desplazamiento en la pintura en elementos contenidos dentro de otro elemento.

Siguiendo me lo resolvió:

        x = e.pageX - this.offsetLeft - $(elem).offset().left;
        y = e.pageY - this.offsetTop - $(elem).offset().top;

En otras palabras, simplemente apilé todos los desplazamientos de todos los elementos anidados

Mate
fuente
+1 para ti! Esta es la respuesta que he estado buscando. Tenía dos lienzos apilados uno encima del otro y las coordenadas estaban mal debido a los otros divs. Sabía que este era el problema, pero no conocía la lógica / ecuación para compensarlo. ¡Acabas de arreglar mi problema también! = D gracias!
Partack
5

Ninguna de las respuestas anteriores es IMO satisfactoria, así que esto es lo que uso:

// Cross-browser AddEventListener
function ael(e, n, h){
    if( e.addEventListener ){
        e.addEventListener(n, h, true);
    }else{
        e.attachEvent('on'+n, h);
    }
}

var touch = 'ontouchstart' in document.documentElement; // true if touch device
var mx, my; // always has current mouse position IN WINDOW

if(touch){
    ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} );
}else{
    ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} );
}

// local mouse X,Y position in element
function showLocalPos(e){
    document.title = (mx - e.getBoundingClientRect().left)
        + 'x'
        + Math.round(my - e.getBoundingClientRect().top);
}

Y si alguna vez necesita saber la posición actual de desplazamiento Y de la página:

var yscroll = window.pageYOffset
        || (document.documentElement && document.documentElement.scrollTop)
        || document.body.scrollTop; // scroll Y position in page
FlorianB
fuente
4

Para aquellos de ustedes que desarrollan sitios web regulares o PWAs (Progressive Web Apps) para dispositivos móviles y / o computadoras portátiles / monitores con pantallas táctiles, entonces han aterrizado aquí porque pueden estar acostumbrados a los eventos del mouse y son nuevos en la experiencia a veces dolorosa de Touch eventos ... yay!

Solo hay 3 reglas:

  1. Haga lo menos posible durante mousemoveo touchmoveeventos.
  2. Haga todo lo posible durante mousedowno touchstarteventos.
  3. Cancele la propagación y evite los valores predeterminados para eventos táctiles para evitar que los eventos del mouse también se activen en dispositivos híbridos.

No hace falta decir que las cosas son más complicadas con los toucheventos porque puede haber más de uno y son más flexibles (complicados) que los eventos del mouse. Solo voy a cubrir un solo toque aquí. Sí, estoy siendo flojo, pero es el tipo de toque más común, así que ahí.

var posTop;
var posLeft;
function handleMouseDown(evt) {
  var e = evt || window.event; // Because Firefox, etc.
  posTop = e.target.offsetTop;
  posLeft = e.target.offsetLeft;
  e.target.style.background = "red";
  // The statement above would be better handled by CSS
  // but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
  var e = evt || window.event;
  var x = e.offsetX; // Wonderfully
  var y = e.offsetY; // Simple!
  e.target.innerHTML = "Mouse: " + x + ", " + y;
  if (posTop)
    e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
  var e = evt || window.event;
  e.target.innerHTML = "";
}
function handleMouseUp(evt) {
  var e = evt || window.event;
  e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
  var e = evt || window.event;
  var rect = e.target.getBoundingClientRect();
  posTop = rect.top;
  posLeft = rect.left;
  e.target.style.background = "green";
  e.preventDefault(); // Unnecessary if using Vue.js
  e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
  var e = evt || window.event;
  var pageX = e.touches[0].clientX; // Touches are page-relative
  var pageY = e.touches[0].clientY; // not target-relative
  var x = pageX - posLeft;
  var y = pageY - posTop;
  e.target.innerHTML = "Touch: " + x + ", " + y;
  e.target.innerHTML += "<br>" + pageX + ", " + pageY;
  e.preventDefault();
  e.stopPropagation();
}
function handleTouchEnd(evt) {
  var e = evt || window.event;
  e.target.style.background = "yellow";
  // Yes, I'm being lazy and doing the same as mouseout here
  // but obviously you could do something different if needed.
  e.preventDefault();
  e.stopPropagation();
}
div {
  background: yellow;
  height: 100px;
  left: 50px;
  position: absolute;
  top: 80px;
  user-select: none; /* Disable text selection */
  -ms-user-select: none;
  width: 100px;
}
<div 
  onmousedown="handleMouseDown()" 
  onmousemove="handleMouseMove()"
  onmouseout="handleMouseOut()"
  onmouseup="handleMouseUp()" 
  ontouchstart="handleTouchStart()" 
  ontouchmove="handleTouchMove()" 
  ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.

¿Prefieres usar Vue.js ? ¡Hago! Entonces su HTML se vería así:

<div @mousedown="handleMouseDown"
     @mousemove="handleMouseMove"
     @mouseup="handleMouseUp"
     @touchstart.stop.prevent="handleTouchStart"
     @touchmove.stop.prevent="handleTouchMove"
     @touchend.stop.prevent="handleTouchEnd">
John T.
fuente
3

puedes conseguirlo

var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
    var xCoor = e.clientX;
    var yCoor = e.clientY;
}
robar waminal
fuente
¿Funcionará en IE, o IE todavía usa window.event en lugar de pasar el evento al primer argumento del oyente? edit - Supongo que IE carece del elemento de lienzo de todos modos hasta la versión 9, pero esto probablemente debería ser compatible con IE debido a cosas como excanvas ...
Dagg Nabbit
21
Esto le dará las coordenadas relativas a la ventana del navegador, aún necesita averiguar si están en el elemento usando element.getBoundingClientRect ()
David W. Keith
gracias por informarme de getBoundingClientRect !!!! ¡Nunca me di cuenta de que había tal cosa!
Gershom
@ DavidW. ¡El comentario de Keith realmente debería considerarse la respuesta correcta!
Ulrik S
3

Tomado de este tutorial , con correcciones hechas gracias al comentario superior:

function getMousePos( canvas, evt ) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ),
        y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height )
    };
}

Usar en un lienzo de la siguiente manera:

var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
    var mousePos = getMousePos( canvas, evt );
} );
Jonathan H
fuente
3

Me doy cuenta de que llego un poco tarde, pero esto funciona con JavaScript PURE, e incluso le da las coordenadas del puntero dentro del elemento si el elemento es más grande que la ventana gráfica y el usuario se ha desplazado.

var element_offset_x ; // The distance from the left side of the element to the left of the content area


....// some code here (function declaration or element lookup )



element_offset_x = element.getBoundingClientRect().left  -  document.getElementsByTagName("html")[0].getBoundingClientRect().left  ;

....// code here 




function mouseMoveEvent(event) 
{
   var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ; 
}

Cómo funciona.

Lo primero que hacemos es obtener la ubicación del elemento HTML (el área de contenido) en relación con la ventana gráfica actual. Si la página tiene barras de desplazamiento y se desplaza, el número devuelto porgetBoundingClientRect().left la etiqueta html será negativo. Luego usamos este número para calcular la distancia entre el elemento y la izquierda del área de contenido. Conelement_offset_x = element.getBoundingClientRect().left......;

Conocer la distancia del elemento desde el área de contenido. event.clientXnos da la distancia del puntero desde la ventana gráfica. Es importante comprender que la ventana gráfica y el área de contenido son dos entidades diferentes, la ventana gráfica puede moverse si se desplaza la página. Por lo tanto, clientX devolverá el MISMO número incluso si se desplaza la página.

Para compensar esto, necesitamos agregar la posición x del puntero (en relación con la ventana gráfica), a la posición x de la ventana gráfica (en relación con el área de contenido). La posición X de la ventana gráfica se encuentra con window.pageXOffset.

FutureSci
fuente
1
Gracias por ser el único respondedor que piensa en desplazarse. Considere cambiar su respuesta para agregar también el eje y.
frabjous
3

Basado en la solución de @ Spider, mi versión no JQuery es esta:

// Get the container element's bounding box
var sides = document.getElementById("container").getBoundingClientRect();

// Apply the mouse event listener
document.getElementById("canvas").onmousemove = (e) => {
  // Here 'self' is simply the current window's context
  var x = (e.clientX - sides.left) + self.pageXOffset;
  var y = (e.clientY - sides.top) + self.pageYOffset;
}

Esto funciona tanto con desplazamiento como con zoom (en cuyo caso a veces devuelve flotantes).

Letokteren
fuente
Votaría, pero ¿no deberían ser signos negativos para los desplazamientos de página? ¿O eso, o los paréntesis alrededor de la segunda parte?
Chris Sunami apoya a Monica el
1

Las coordenadas del mouse dentro de un lienzo se pueden obtener gracias a event.offsetX y event.offsetY. Aquí hay un pequeño fragmento para probar mi punto:

c=document.getElementById("c");
ctx=c.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
c.addEventListener("mousemove",function(mouseEvt){
  // the mouse's coordinates on the canvas are just below
  x=mouseEvt.offsetX;
  y=mouseEvt.offsetY;
  // the following lines draw a red square around the mouse to prove it
  ctx.fillStyle="black";
  ctx.fillRect(0,0,100,100);
  ctx.fillStyle="red";
  ctx.fillRect(x-5,y-5,10,10);
});
  
body {
  background-color: blue;
}

canvas {
  position: absolute;
  top: 50px;
  left: 100px;
}
<canvas id="c" width="100" height="100"></canvas>
    

Nino Filiu
fuente
No funciona si otro div está superponiendo el lienzo, como dijo @opsb
David Peicho el
1
canvas.onmousedown = function(e) {
    pos_left = e.pageX - e.currentTarget.offsetLeft;
    pos_top = e.pageY - e.currentTarget.offsetTop;
    console.log(pos_left, pos_top)
}

HTMLElement.offsetLeft

La HTMLElement.offsetLeftpropiedad de solo lectura devuelve el número de píxeles que la esquina superior izquierda del elemento actual está desplazada a la izquierda dentro delHTMLElement.offsetParent nodo.

Para los elementos a nivel de bloque, offsetTop, offsetLeft, offsetWidth, y offsetHeightdescribir el cuadro de borde de un elemento con respecto a la offsetParent.

Sin embargo, para elementos de nivel en línea (como span) que pueden ajustarse de una línea a la siguiente, offsetTopyoffsetLeft describir las posiciones del primer cuadro de borde (usar Element.getClientRects()para obtener su ancho y alto), mientras que offsetWidthy offsetHeightdescribir las dimensiones del cuadro de borde delimitador (use Element.getBoundingClientRect()para obtener su posición). Por lo tanto, una caja con la izquierda, superior, anchura y altura de offsetLeft, offsetTop, offsetWidthy offsetHeightno será un cuadro delimitador por una duración con el texto envuelto.

HTMLElement.offsetTop

La HTMLElement.offsetToppropiedad de solo lectura devuelve la distancia del elemento actual en relación con la parte superior del offsetParentnodo.

MouseEvent.pageX

La pageXpropiedad de solo lectura devuelve la coordenada X (horizontal) en píxeles del evento en relación con todo el documento. Esta propiedad tiene en cuenta cualquier desplazamiento horizontal de la página.

MouseEvent.pageY

La MouseEvent.pageYpropiedad de solo lectura devuelve la coordenada Y (vertical) en píxeles del evento en relación con todo el documento. Esta propiedad tiene en cuenta cualquier desplazamiento vertical de la página.

Para obtener más información, consulte la red de desarrolladores de Mozilla:

https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY https: // developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop

lama12345
fuente
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código.
Patrick Hund
Realmente espero que los lectores en el futuro tengan una API JS que calcule esto para ellos. ;-) Esta es probablemente la respuesta más simple, completa y autónoma. Comentar un código que se explica por sí solo es una distracción.
lama12345
Apoyo la solicitud de @ PatrickHund de una explicación. No soy un experto en CSS / JS, y conocer más sobre las relaciones entre, por ejemplo, pagey offsetsería muy útil para mí. ¡Gracias por considerar esta solicitud!
cxw
@cxw Ok, ahora eres el segundo voto negativo (tenía 1 voto positivo) ... Agregué una explicación larga ahora, es como 10 veces más larga que las 4 líneas de código. De nada, diviértete leyendo. ¡He considerado tu solicitud! : p
lama12345
1
@cxw Me equivoqué agregando un elemento extra absoluto posicionado y forzando también el elemento de lienzo fuera de la pantalla, así que tuve que desplazarme hacia él, como izquierda / arriba 2000px fuera de la pantalla. No se pudo romper este código.
lama12345
1

Implementé otra solución que creo que es muy simple, así que pensé en compartirla con ustedes.

Entonces, el problema para mí fue que el div arrastrado saltaría a 0,0 para el cursor del mouse. Así que necesitaba capturar la posición de los ratones en el div para ajustar la nueva posición del divs.

Leo los divs PageX y PageY y establezco la parte superior e izquierda de acuerdo con eso y luego para obtener los valores para ajustar las coordenadas para mantener el cursor en la posición inicial en el div, uso un escucha onDragStart y almaceno el e.nativeEvent .layerX y e.nativeEvent.layerY que solo en el disparador inicial le da la posición de los ratones dentro del div arrastrable.

Código de ejemplo:

 onDrag={(e) => {
          let newCoords;
          newCoords = { x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY };
          this.props.onDrag(newCoords, e, item.id);
        }}
        onDragStart={
          (e) => {
            this.setState({
              correctionX: e.nativeEvent.layerX,
              correctionY: e.nativeEvent.layerY,
            });
          }

Espero que esto ayude a alguien que pasó por los mismos problemas que yo pasé :)

Athinodoros Sgouromallis
fuente
1
function myFunction(e) {
    var x =  e.clientX - e.currentTarget.offsetLeft ; 
    var y = e.clientY - e.currentTarget.offsetTop ;
}

esto funciona bien!

M9J_cfALt
fuente
0

Tienes que conocer la estructura de tu página, porque si tu lienzo es hijo de un div que a su vez es hijo de otro div ... entonces la historia se vuelve más complicada. Aquí está mi código para un lienzo que está dentro de 2 niveles de div s:

canvas.addEventListener("click", function(event) {
var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft);
var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop);
console.log("relative x=" + x, "relative y" + y);

});

Eli Mashiah
fuente
0

La respuesta original decía ponerlo en un iframe. La mejor solución es usar los eventos offsetX y offsetY en un lienzo que tenga el relleno establecido en 0px.

<html>
<body>
<script>

var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);

// adding event listener

main.addEventListener('mousemove',function(e){
    var ctx=e.target.getContext('2d');
    var c=Math.floor(Math.random()*0xFFFFFF);
    c=c.toString(16); for(;c.length<6;) c='0'+c;
    ctx.strokeStyle='#'+c;
    ctx.beginPath();
    ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
    ctx.stroke();
    e.target.title=e.offsetX+' '+e.offsetY;
    });

// it worked! move mouse over window

</script>
</body>
</html>
Smertrios2007
fuente
0

Esto es lo que tengo.

    $(".some-class").click(function(e) {

    var posx = 0;
    var posy = 0;

    posx = e.pageX;
    posy = e.pageY;

    alert(posx);
    alert(posy);
});
Shmoo
fuente
0

Puedes usar getBoudingClientRect()el relativepadre.

document.addEventListener("mousemove", (e) => {
  let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
  let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
  console.log("xCoord", xCoord, "yCoord", yCoord)
})
BrieucKyo
fuente