Javascript: traccia la posizione del mouse


161

Spero di tenere traccia della posizione del cursore del mouse, periodicamente ogni t msecondi. Quindi, essenzialmente, quando viene caricata una pagina - questo tracker dovrebbe avviarsi e per (diciamo) ogni 100 ms, dovrei ottenere il nuovo valore di posX e posY e stamparlo nel modulo.

Ho provato il seguente codice, ma i valori non vengono aggiornati: solo i valori iniziali di posX e posY vengono visualizzati nelle caselle del modulo. Qualche idea su come posso farlo funzionare?

<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>

Il problema è che non ci saranno eventoggetti quando la funzione viene chiamata per la seconda volta. Probabilmente dovresti ascoltare qualche evento che usare setTimeout.
Felix Kling,

Sì, ma la funzione mouse_position () non dovrebbe continuare a chiamarsi ogni 100 millisecondi. In realtà non dovrebbe comportarsi come una funzione ricorsiva infinita?
Hari,

2
possibile duplicato della posizione del mouse
Shadow Wizard is Ear For You

@Titan: Sì, ma sospetto che si verifichi un errore perché window.eventsarà undefinedo null. Se non è presente alcun evento, non esiste alcun eventoggetto.
Felix Kling

1
per interesse, qual è l'applicazione di questo?
SuperUberDuper

Risposte:


178

La posizione del mouse è riportata sul event sull'oggetto ricevuto da un gestore per l' mousemoveevento, che è possibile collegare alla finestra (bolle dell'evento):

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

(Si noti che il corpo di questo ifverrà eseguito solo su IE precedente.)

Esempio di quanto sopra in azione : disegna punti mentre trascini il mouse sulla pagina. (Testato su IE8, IE11, Firefox 30, Chrome 38.)

Se hai davvero bisogno di una soluzione basata sul timer, combinala con alcune variabili di stato:

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

Per quanto ne so, non puoi ottenere la posizione del mouse senza aver visto un evento, qualcosa a cui questa risposta ad un'altra domanda Stack Overflow sembra confermare.

Nota a margine : se hai intenzione di fare qualcosa ogni 100 ms (10 volte / secondo), prova a mantenere l'elaborazione effettiva che svolgi in quella funzione molto, molto limitata . Questo è molto lavoro per il browser, in particolare quelli più vecchi di Microsoft. Sì, sui computer moderni non sembra molto, ma c'è molto da fare nei browser ... Quindi, ad esempio, potresti tenere traccia dell'ultima posizione che hai elaborato e salvarti immediatamente dal gestore se la posizione non ha ' è cambiato.


66

Ecco una soluzione, basata su jQuery e un listener di eventi del mouse (che è molto meglio di un normale polling) sul corpo:

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

Come ho già detto, il polling regolare è esattamente quello che voglio fare. Non sto monitorando le modifiche negli eventi del mouse, sto solo cercando di catturare la posizione del mouse ogni x millisecondi (indipendentemente dal fatto che il mouse si sia spostato o meno).
Hari,

3
Perché tenere traccia di un valore che sicuramente conosci non è cambiato? Non capisco, a meno che non si tratti di un problema di compiti a casa. Con il metodo dell'evento, è possibile tenere traccia di ogni modifica di questi valori, quindi eseguire un polling di 100 ms altrove se è necessario gestire questi valori per qualsiasi scopo.
solendil,

1
Non c'è alcun vantaggio nell'utilizzare jQuery qui se non l'uso inutile di una lib JS da 5 MB
Pattycake Jr

@PattycakeJr L'ultima volta che l'ho visto era sotto i 90kB nella versione ridotta
Kris

1
@PattycakeJr anche se sei super improbabile che lo scarichi affatto se indichi un CDN poiché quasi tutti gli altri siti lo collegano
Brian Leishman,

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

Apri la tua console ( Ctrl+ Shift+ J), copia e incolla il codice sopra e sposta il mouse sulla finestra del browser.


1
Imo la migliore risposta
Ecco il

10

Credo che stiamo pensando troppo a questo,

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


1
Sono nuovo di questo forum, quindi, per questo, lo so, ti prego di spiegare perché tu e il mio tendalino, è così che non commetto più lo stesso errore. Grazie! ThePROgrammer
dGRAMOP

10
Anch'io sono seccato dai voti negativi senza spiegazioni. Per darvi una possibile spiegazione, questa risposta non affronta il problema del PO di polling ogni 100 ms. È più chiaro nella sua risposta ad altre risposte che questa è una necessità.
aaaaaa,

1
anche questo tipo di gestione degli eventi in linea è deprecato, credo. document.body.addEventListener("mousemove", function (e) {})è il modo per farlo, nel tuo codice javascript invece che nell'html
Ryan

10

Quello che penso che vuole solo conoscere le posizioni X / Y del cursore del perché la risposta è così complicata.

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

Codice basato su ES6:

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

document.addEventListener('mousemove', handleMousemove);

Se hai bisogno di limitazione per il movimento del mouse, usa questo:

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

ecco un esempio


2

Indipendentemente dal browser, sotto le righe ha funzionato per me per recuperare la posizione corretta del mouse.

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


2

Se vuoi solo tracciare visivamente il movimento del mouse:

<!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

Non ho abbastanza reputazione per pubblicare un commento, ma ho preso l' eccellente risposta di TJ Crowder e ho definito completamente il codice su un timer da 100 ms . (Ha lasciato alcuni dettagli all'immaginazione.)

Grazie OP per la domanda e TJ per la risposta! Sei di grande aiuto. Il codice è incorporato di seguito come mirror di 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

Ecco una combinazione dei due requisiti: traccia la posizione del mouse, ogni 100 millisecondi:

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

Questo tiene traccia e agisce sulla posizione del mouse, ma solo ogni periodo millisecondi.


0

Solo una versione semplificata delle risposte di @TJ Crowder e @RegarBoy .

Meno è più secondo me.

Controlla l' evento onmousemove per maggiori informazioni sull'evento.

Tracker mouse immagine

C'è un nuovo valore di posXe posYogni volta che il mouse si sposta in base alle coordinate orizzontali e verticali.

<!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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.