Javascript - Rastrea la posición del mouse


161

Espero rastrear la posición del cursor del mouse, periódicamente cada t ms. Entonces, esencialmente, cuando se carga una página: este rastreador debería iniciarse y (por ejemplo) cada 100 ms, debería obtener el nuevo valor de posX y posY e imprimirlo en el formulario.

Intenté el siguiente código, pero los valores no se actualizan, solo los valores iniciales de posX y posY aparecen en los cuadros de formulario. ¿Alguna idea sobre cómo puedo poner esto en funcionamiento?

<html>
<head>
<title> Track Mouse </title>
<script type="text/javascript">
function mouse_position()
{
    var e = window.event;

    var posX = e.clientX;
    var posY = e.clientY;

    document.Form1.posx.value = posX;
    document.Form1.posy.value = posY;

    var t = setTimeout(mouse_position,100);

}
</script>

</head>

<body onload="mouse_position()">
<form name="Form1">
POSX: <input type="text" name="posx"><br>
POSY: <input type="text" name="posy"><br>
</form>
</body>
</html>

El problema es que no habrá ningún eventobjeto cuando se llame a la función por segunda vez. Probablemente deberías escuchar algún evento que usar setTimeout.
Felix Kling

Sí, pero la función mouse_position () no debería llamarse a sí misma cada 100 milisegundos. ¿No debería realmente comportarse como una función recursiva infinita?
Hari


@Titan: Sí, pero sospecho que será un error porque window.eventserá undefinedo null. Si no hay evento, no hay eventobjeto.
Felix Kling

1
fuera de interés, ¿cuál es la aplicación de esto?
SuperUberDuper

Respuestas:


178

La posición del mouse se informa sobre el eventobjeto recibido por un controlador para el mousemoveevento, que puede adjuntar a la ventana (el evento burbujea):

(function() {
    document.onmousemove = handleMouseMove;
    function handleMouseMove(event) {
        var eventDoc, doc, body;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        // Use event.pageX / event.pageY here
    }
})();

(Tenga en cuenta que el cuerpo de eso ifsolo se ejecutará en IE antiguo).

Ejemplo de lo anterior en acción : dibuja puntos mientras arrastra el mouse sobre la página. (Probado en IE8, IE11, Firefox 30, Chrome 38.)

Si realmente necesita una solución basada en temporizador, combine esto con algunas variables de estado:

(function() {
    var mousePos;

    document.onmousemove = handleMouseMove;
    setInterval(getMousePosition, 100); // setInterval repeats every X ms

    function handleMouseMove(event) {
        var dot, eventDoc, doc, body, pageX, pageY;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        mousePos = {
            x: event.pageX,
            y: event.pageY
        };
    }
    function getMousePosition() {
        var pos = mousePos;
        if (!pos) {
            // We haven't seen any movement yet
        }
        else {
            // Use pos.x and pos.y
        }
    }
})();

Hasta donde sé, no puede obtener la posición del mouse sin haber visto un evento, algo que esta respuesta a otra pregunta de Stack Overflow parece confirmar.

Nota al margen : si va a hacer algo cada 100 ms (10 veces / segundo), intente mantener el procesamiento real que realiza en esa función muy, muy limitado . Eso es mucho trabajo para el navegador, particularmente los más antiguos de Microsoft. Sí, en las computadoras modernas no parece mucho, pero están sucediendo muchas cosas en los navegadores ... Entonces, por ejemplo, puede realizar un seguimiento de la última posición que procesó y abandonar el controlador inmediatamente si la posición no ha cambiado. t cambiado.


66

Aquí hay una solución, basada en jQuery y un detector de eventos de mouse (que es mucho mejor que un sondeo regular) en el cuerpo:

$("body").mousemove(function(e) {
    document.Form1.posx.value = e.pageX;
    document.Form1.posy.value = e.pageY;
})

Como mencioné, las encuestas regulares son exactamente lo que quiero hacer. No estoy siguiendo los cambios en los eventos del mouse, solo estoy buscando capturar la posición del mouse cada x milisegundos (independientemente de si el mouse se movió o no).
Hari

3
¿Por qué el seguimiento de un valor que sabes con certeza no cambió? No entiendo, a menos que sea un problema de tarea. Con el método de evento, puede realizar un seguimiento de cada cambio de estos valores, luego realizar un sondeo de 100 ms en otro lugar si necesita manejar estos valores para cualquier propósito.
solendil

1
No hay ninguna ventaja de usar jQuery aquí, excepto usar innecesariamente una lib de 5mb JS
Pattycake Jr

@PattycakeJr La última vez que miré tenía menos de 90kB en la versión minificada
Kris

1
@PattycakeJr también si es muy poco probable que lo descargues si apuntas a un CDN ya que casi todos los sitios enlazan a él
Brian Leishman

53
onmousemove = function(e){console.log("mouse location:", e.clientX, e.clientY)}

Abra su consola ( Ctrl+ Shift+ J), copie y pegue el código anterior y mueva el mouse en la ventana del navegador.


1
Imo la mejor respuesta
Aquí Aquí

10

Creo que estamos pensando demasiado en esto,

function mouse_position(e)
{
//do stuff
}
<body onmousemove="mouse_position(event)"></body>


1
Soy nuevo en este foro, así que, por lo que sé, explique por qué usted y mi abucheador, esto es para que no vuelva a cometer el mismo error. ¡Gracias! ThePROgrammer
dGRAMOP

10
A mí también me molestan los votos negativos sin explicación. Para darle una posible explicación, esta respuesta no aborda el problema del OP de sondear cada 100 ms. Es más claro en su respuesta a otras respuestas que esto es una necesidad.
aaaaaa

1
También este tipo de gestión de eventos en línea está en desuso, creo. document.body.addEventListener("mousemove", function (e) {})es la forma de hacer esto, en su código de JavaScript en lugar de en el html
Ryan

10

Lo que creo que solo quiere saber es la posición X / Y del cursor que por qué la respuesta es tan complicada.

// Getting 'Info' div in js hands
var info = document.getElementById('info');

// Creating function that will tell the position of cursor
// PageX and PageY will getting position values and show them in P
function tellPos(p){
  info.innerHTML = 'Position X : ' + p.pageX + '<br />Position Y : ' + p.pageY;
}
addEventListener('mousemove', tellPos, false);
* {
  padding: 0:
  margin: 0;
  /*transition: 0.2s all ease;*/
  }
#info {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: black;
  color: white;
  padding: 25px 50px;
}
<!DOCTYPE html>
<html>
  
  <body>
    <div id='info'></div>
        </body>
  </html>


5

Código basado en ES6:

let handleMousemove = (event) => {
  console.log(`mouse position: ${event.x}:${event.y}`);
};

document.addEventListener('mousemove', handleMousemove);

Si necesita aceleración para mover el mouse, use esto:

let handleMousemove = (event) => {
  console.warn(`${event.x}:${event.y}\n`);
};

let throttle = (func, delay) => {
  let prev = Date.now() - delay;
  return (...args) => {
    let current = Date.now();
    if (current - prev >= delay) {
      prev = current;
      func.apply(null, args);
    }
  }
};

// let's handle mousemoving every 500ms only
document.addEventListener('mousemove', throttle(handleMousemove, 500));

aquí hay un ejemplo


2

Independientemente del navegador, las siguientes líneas me funcionaron para obtener la posición correcta del mouse.

event.clientX - event.currentTarget.getBoundingClientRect().left event.clientY - event.currentTarget.getBoundingClientRect().top


2

Si solo desea seguir el movimiento del mouse visualmente:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<style type="text/css">
* { margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; overflow: hidden; }
</style>
<body>
<canvas></canvas>

<script type="text/javascript">
var
canvas    = document.querySelector('canvas'),
ctx       = canvas.getContext('2d'),
beginPath = false;

canvas.width  = window.innerWidth;
canvas.height = window.innerHeight;

document.body.addEventListener('mousemove', function (event) {
	var x = event.clientX, y = event.clientY;

	if (beginPath) {
		ctx.lineTo(x, y);
		ctx.stroke();
	} else {
		ctx.beginPath();
		ctx.moveTo(x, y);
		beginPath = true;
	}
}, false);
</script>
</body>
</html>


2

No tengo suficiente reputación para publicar una respuesta de comentario, pero tomé la excelente respuesta de TJ Crowder y definí completamente el código en un temporizador de 100 ms . (Dejó algunos detalles a la imaginación).

Gracias OP por la pregunta, y TJ por la respuesta. Ambos son de gran ayuda. El código está incrustado a continuación como un espejo de isbin.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Example</title>
  <style>
    body {
      height: 3000px;
    }
    .dot {
      width: 2px;
      height: 2px;
      background-color: black;
      position: absolute;
    }
  </style>
</head>
<body>
<script>
(function() {
    "use strict";
    var mousePos;

    document.onmousemove = handleMouseMove;
    setInterval(getMousePosition, 100); // setInterval repeats every X ms

    function handleMouseMove(event) {
        var eventDoc, doc, body;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        mousePos = {
            x: event.pageX,
            y: event.pageY
        };
    }
    function getMousePosition() {
        var pos = mousePos;
		
        if (!pos) {
            // We haven't seen any movement yet, so don't add a duplicate dot 
        }
        else {
            // Use pos.x and pos.y
            // Add a dot to follow the cursor
            var dot;
            dot = document.createElement('div');
            dot.className = "dot";
            dot.style.left = pos.x + "px";
            dot.style.top = pos.y + "px";
            document.body.appendChild(dot);
        }
    }
})();
</script>
</body>
</html>


0

Aquí hay una combinación de los dos requisitos: rastrear la posición del mouse, cada 100 milisegundos:

var period = 100,
    tracking;

window.addEventListener("mousemove", function(e) {
    if (!tracking) {
        return;
    }

    console.log("mouse location:", e.clientX, e.clientY)
    schedule();
});

schedule();

function schedule() {
    tracking = false;

    setTimeout(function() {
        tracking = true;
    }, period);
}

Esto rastrea y actúa en la posición del mouse, pero solo cada período de milisegundos.


0

Solo una versión simplificada de las respuestas de @TJ Crowder y @RegarBoy .

Menos es más en mi opinión.

Consulte el evento onmousemove para obtener más información sobre el evento.

Rastreador de mouse de imagen

Hay un nuevo valor de posXy posYcada vez que el mouse se mueve de acuerdo con las coordenadas horizontales y verticales.

<!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Example Mouse Tracker</title>
      <style>    
        body {height: 3000px;}
        .dot {width: 2px;height: 2px;background-color: black;position: absolute;}
      </style>
    </head>
    <body>
    <p>Mouse tracker</p>
    <script>
    onmousemove = function(e){
        //Logging purposes
        console.log("mouse location:", e.clientX, e.clientY);

        //meat and potatoes of the snippet
        var pos = e;
        var dot;
        dot = document.createElement('div');
        dot.className = "dot";
        dot.style.left = pos.x + "px";
        dot.style.top = pos.y + "px";
        document.body.appendChild(dot);
    }      
    </script>
    </body>
    </html>
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.