Come ottenere la posizione del mouse senza eventi (senza spostare il mouse)?


286

È possibile ottenere la posizione del mouse con JavaScript dopo il caricamento della pagina senza alcun evento di spostamento del mouse (senza spostare il mouse)?


61
Niente di sbagliato con l'evento mousemove. Solo in alcuni casi gli utenti non muovono il mouse. Grazie per la tua risposta.
Norbert Tamas,

2
Norbert Tamas, la risposta di @ SuperNova (che non è stata aggiunta fino a quest'anno) mostra che mouseenter funziona bene perché si attiva al caricamento della pagina (se il mouse è nella finestra). Non ha funzionato in questo modo nel 2010 o è solo che nessuno ha pensato di provarlo?
Peter Hansen,

@CrescentFresh In alcuni casi (come gli script utente) non si desidera rallentare il browser aggiungendo molti mousemoveeventi.
Tomáš Zato - Ripristina Monica il

Possibile in formato FF con passaggio del mouse, ma non in IE e Chrome.
Elad,

Oppure, in un gioco, la tua videocamera si sposta nel mondo di gioco e il personaggio guarda il mouse (tipico stile sparatutto dall'alto in basso) ma se l'utente non sposta un mouse, si centra attorno al punto sbagliato mentre ti muovi se fai affidamento solo su mousemove. Tuttavia, non è un grosso problema, memorizziamo solo le coordinate "mondiali" del puntatore e consentiamo alle persone di interrogarlo.
kamranicus,

Risposte:


336

Risposta reale: No, non è possibile.

OK, ho appena pensato a un modo. Sovrapponi la tua pagina con un div che copre l'intero documento. Al suo interno, crea (diciamo) 2.000 x 2.000 <a>elementi (in modo che la :hoverpseudo-classe funzioni in IE 6, vedi), ogni 1 pixel di dimensioni. Crea una :hoverregola CSS per quegli <a>elementi che cambiano una proprietà (diciamo font-family). Nel gestore del carico, scorrere ciascuno dei 4 milioni di <a>elementi, controllando currentStyle/ getComputedStyle()fino a trovare quello con il carattere al passaggio del mouse. Estrapola indietro da questo elemento per ottenere le coordinate all'interno del documento.

NB NON FARE QUESTO .


92
ah ah - a un certo punto dovresti andare su Google e vedere se riesci a capire quante persone hanno effettivamente implementato questo
Pointy

6
In realtà, è implementabile senza dover caricare molto la CPU (penso. Non l'ho provato). Su dom ready costruisci gli elementi <a> con javascript, prendi la posizione del mouse e rimuovi tutti gli elementi <a>. Su mousemouse dovresti avere un'altra funzione per assumere la posizione del mouse. Comunque, questo è stato divertente.
machineaddict

21
Forse questo potrebbe essere reso pratico con la ricerca binaria? Effettua un ciclo di creazione di una coppia di <a>elementi che coprono determinati rettangoli (usando il posizionamento assoluto di <img>elementi di dimensioni , suppongo), riducendo i rettangoli ogni volta. Sì, è ridicolo, ma non è possibile ottenere queste informazioni prima del primo mousemove.
Darius Bacon,

29
stackoverflow.com/a/8543879/27024 afferma che l'hover non si attiva neanche fino a quando il mouse non si sposta per la prima volta. Questo sventa questo schema.
Darius Bacon,

4
@DariusBacon: la risposta collegata non sembra corretta: jsbin.com/utocax/3 . Quindi sì, questo approccio può essere pratico per alcune situazioni.
Tim Down,

121

Modifica 2020: questo non funziona più. Sembra che i fornitori di browser abbiano risolto il problema. Poiché la maggior parte dei browser si basa sul cromo, potrebbe essere nel suo nucleo.

Vecchia risposta: puoi anche agganciare il mouseenter (questo evento viene generato dopo il ricaricamento della pagina, quando il cursore del mouse è all'interno della pagina). L'estensione del codice di Corrupted dovrebbe fare il trucco:

var x = null;
var y = null;
    
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
    
function onMouseUpdate(e) {
  x = e.pageX;
  y = e.pageY;
  console.log(x, y);
}

function getMouseX() {
  return x;
}

function getMouseY() {
  return y;
}

Puoi anche impostare xey su null su mouseleave-event. Quindi puoi verificare se l'utente è sulla tua pagina con il suo cursore.


11
Questa sembrerebbe essere l'unica risposta davvero utile qui, che sembra strana. Infatti (negli ultimi Firefox, Chrome e IE11) il mouseenter si attiva al caricamento della pagina e fornisce le coordinate corrette. Il comportamento del browser in quest'area è semplicemente cambiato negli ultimi anni?
Peter Hansen,

3
In effetti "mouseenter" non sembra aggiungere alcun valore. Ho provato con il seguente jsfiddle in Chrome e IE, e non mostrano le coordinate fino a quando non si posiziona il mouse sul documento interno (il pannello dei risultati): jsfiddle.net/xkpd784o/1
Mariano Desanze

1
@Proton: spostare il mouse sul pannello dei risultati nell'area del pannello dei risultati PRIMA che la pagina sia stata caricata completamente e non spostarsi di. Dopo aver caricato la pagina, conosce immediatamente la posizione del mouse. Non è necessario alcun movimento del mouse. Quindi anche il mouseenter viene attivato quando la pagina è stata caricata e il mouse si trova all'interno dell'area del documento. Cioè, ciò che l'OP inizialmente voleva. Nessun altro fornisce questa risposta.
SuperNova,

1
Un'aggiunta potenzialmente utile è quella di aggiungere una funzione per l' mouseleaveevento che imposta xe ytorna a nullo'undefined'
rtpax il

2
chrome 68, utilizzando il jsfiddel sopra, l'avviso si verifica al primo spostamento del mouse e non al caricamento, anche se il mouse viene spostato nell'area di rendering prima che il caricamento della pagina sia terminato.
Junvar

84

Quello che puoi fare è creare variabili per xe ycoordinate del cursore, aggiornarle ogni volta che il mouse si sposta e chiamare una funzione su un intervallo per fare ciò di cui hai bisogno con la posizione memorizzata.

L'aspetto negativo di questo ovviamente è che è necessario almeno un movimento iniziale del mouse per farlo funzionare. Finché il cursore aggiorna la sua posizione almeno una volta, siamo in grado di trovare la sua posizione indipendentemente dal fatto che si muova di nuovo.

var cursorX;
var cursorY;
document.onmousemove = function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
}
setInterval(checkCursor, 1000);
function checkCursor(){
    alert("Cursor at: " + cursorX + ", " + cursorY);
}

Il codice precedente si aggiorna una volta al secondo con un messaggio di dove si trova il cursore. Spero che aiuti.


18
Hai letto l'argomento di questo post? L'OP chiede come ottenere le coordinate del mouse senza usare un evento. Eppure il tuo post suggerisce di usare l'evento onmousemove.
jake,

53
@jake Sebbene l'OP abbia specificamente richiesto un metodo di non-evento, questa risposta è di beneficio agli altri che sono venuti qui in cerca di una risposta e possibilmente una soluzione alternativa. Inoltre, considererei questa risposta parzialmente all'interno dell'argomento poiché, per quanto ne so, questo è il metodo migliore per ottenere la posizione del cursore in qualsiasi momento senza dover utilizzare direttamente gli eventi. Detto questo, la risposta avrebbe potuto essere formulata più sulla falsariga di affermare il fatto e di offrire un modo per evitare di rispondere ai commenti.
jpeltoniemi,

2
@Pichan Non mi ha giovato, perché ho cercato un modo per riempire quella cursorX/Yvariabile prima che accadesse qualsiasi evento.
polkovnikov.ph,

pochissimi utenti non
lanceranno

1
Attento, può essere costoso tenere un ascoltatore mousemove in giro. Suggerirei di ricreare l'ascoltatore nell'intervallo e di distruggere l'ascoltatore dopo aver ottenuto le coordinate.
KRB

10

Potresti provare qualcosa di simile a quello che ha suggerito Tim Down, ma invece di avere elementi per ogni pixel sullo schermo, crea solo 2-4 elementi (scatole) e modifica la loro posizione, larghezza, altezza in modo dinamico per dividere le posizioni ancora possibili sullo schermo 2-4 ricorsivamente, trovando così rapidamente la posizione reale del mouse.

Ad esempio: i primi elementi prendono la metà destra e sinistra dello schermo, quindi la metà superiore e inferiore. Ormai sappiamo già in quale quarto di schermo si trova il mouse, sono in grado di ripetere - scopri quale quarto di questo spazio ...


9

La risposta di @Tim Down non è efficace se si rendono 2.000 x 2.000 <a>elementi:

OK, ho appena pensato a un modo. Sovrapponi la tua pagina con un div che copre l'intero documento. Al suo interno, crea (diciamo) 2.000 x 2.000 elementi (in modo che la pseudo-classe: hover funzioni in IE 6, vedi), ogni 1 pixel di dimensione. Crea un CSS: regola al passaggio del mouse per quegli elementi che cambiano una proprietà (diciamo font-family). Nel gestore del carico, scorrere ciascuno dei 4 milioni di elementi, controllando currentStyle / getComputedStyle () fino a trovare quello con il carattere hover. Estrapola indietro da questo elemento per ottenere le coordinate all'interno del documento.

NB NON FARE QUESTO.

Ma non devi renderizzare 4 milioni di elementi contemporaneamente, usa invece la ricerca binaria. Usa <a>invece 4 elementi invece:

  • Passaggio 1: considera l'intero schermo come area di ricerca iniziale
  • Passaggio 2: dividere l'area di ricerca in 2 x 2 = 4 <a>elementi rettangolari
  • Passaggio 3: utilizzando la getComputedStyle()funzione, determinare in quale punto del mouse si trova il rettangolo
  • Passaggio 4: ridurre l'area di ricerca a quel rettangolo e ripetere dal passaggio 2.

In questo modo dovresti ripetere questi passaggi per 11 volte, considerando che il tuo schermo non è più largo di 2048 px.

Quindi genererai un massimo di 11 x 4 = 44 <a>elementi.

Se non è necessario determinare la posizione del mouse esattamente su un pixel, ma dire che la precisione di 10px è OK. Ripetere i passaggi al massimo 8 volte, quindi è necessario disegnare un massimo di 8 x 4 = 32 <a>elementi.

Anche generare e poi distruggere gli <a>elementi non è performat poiché DOM è generalmente lento. Invece, si può semplicemente riutilizzare i primi 4 <a>elementi e basta regolare la loro top, left, widthe heightcome si ciclo attraverso passaggi.

Ora, anche la creazione di 4 <a>è eccessiva. Invece, è possibile riutilizzare lo stesso <a>elemento per quando si esegue il test getComputedStyle()in ogni rettangolo. Quindi, invece di dividere l'area di ricerca in 2 x 2 <a>elementi basta riutilizzare un singolo <a>elemento spostandolo con tope le leftproprietà dello stile.

Quindi, tutto ciò che serve è un singolo <a>elemento che cambia il suo widthe heightmax 11 volte, e cambia il suo tope leftmax 44 volte e avrai la posizione esatta del mouse.


3

La soluzione più semplice ma non accurata al 100%

$(':hover').last().offset()

Risultato: {top: 148, left: 62.5}
il risultato dipende dalla dimensione dell'elemento più vicino e ritorna undefinedquando l'utente cambia scheda


Per me, ritorna a undefinedprescindere. Puoi spiegarci come usarlo?
tresf

Sarebbe tornato undefinedquando il cursore non stava spostando alcun elemento (o quando il browser ha perso lo stato attivo). Potrebbe essere necessario impostare un intervallo di tempo se si
esegue il

Grazie. setTimeoutlavorato. Stavo usando jsfiddle e hai ragione, non ha mai colpito un evento hover perché ridisegna il DOM ogni volta che fai clic su Riproduci. Consiglierei di aggiungere questo suggerimento per gli altri.
martedì

Non voglio una posizione precisa del mouse, ma voglio solo sapere che il mouse è estremamente a destra o all'estrema sinistra in funzione senza oggetto evento, quindi la tua soluzione funziona nel mio caso ... grazie
Swap-IOS-Android

2

Immagino che forse hai una pagina principale con un timer e dopo un certo periodo di tempo o un'attività è stata completata, inoltri l'utente a una nuova pagina. Ora vuoi la posizione del cursore e, poiché stanno aspettando, non stanno necessariamente toccando il mouse. Quindi traccia il mouse sulla pagina principale usando gli eventi standard e passa l'ultimo valore alla nuova pagina in una variabile get o post.

Puoi usare il codice di JHarding sulla tua pagina principale in modo che l'ultima posizione sia sempre disponibile in una variabile globale:

var cursorX;
var cursorY;
document.onmousemove = function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
}

Questo non aiuterà gli utenti che accedono a questa pagina con mezzi diversi dalla tua pagina principale.


1

Ho implementato una ricerca orizzontale / verticale, (prima creai un div pieno di collegamenti di linea verticali disposti orizzontalmente, quindi crea un div pieno di collegamenti di linee orizzontali disposti verticalmente e vedi semplicemente quale ha lo stato al passaggio del mouse) come l'idea di Tim Down sopra, e funziona abbastanza velocemente. Purtroppo, non funziona su Chrome 32 su KDE.

jsfiddle.net/5XzeE/4/


apparentemente questi trucchi non funzionano più a meno che non ci sia un movimento esplicito del mouse da parte dell'utente. :(
trusktr,

1

Non è necessario spostare il mouse per ottenere la posizione del cursore. La posizione viene inoltre segnalata su eventi diversi da mousemove . Ecco un evento click come esempio:

document.body.addEventListener('click',function(e)
{
    console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});

1

Riffing sulla risposta di @ SuperNova , ecco un approccio che utilizza le classi ES6 che mantiene il contesto thiscorretto nel callback:

class Mouse {
  constructor() {
    this.x = 0;
    this.y = 0;
    this.callbacks = {
      mouseenter: [],
      mousemove: [],
    };
  }

  get xPos() {
    return this.x;
  }

  get yPos() {
    return this.y;
  }

  get position() {
    return `${this.x},${this.y}`;
  }

  addListener(type, callback) {
    document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct
    this.callbacks[type].push(callback);
  }

  // `handleEvent` is part of the browser's `EventListener` API.
  // https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent
  handleEvent(event) {
    const isMousemove = event.type === 'mousemove';
    const isMouseenter = event.type === 'mouseenter';

    if (isMousemove || isMouseenter) {
      this.x = event.pageX;
      this.y = event.pageY;
    }

    this.callbacks[event.type].forEach((callback) => {
      callback();
    });
  }
}

const mouse = new Mouse();

mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));


1

Ecco la mia soluzione Esporta window.currentMouseX e window.currentMouseY proprietà che è possibile utilizzare ovunque. Utilizza la posizione di un elemento al passaggio del mouse (se presente) inizialmente e successivamente ascolta i movimenti del mouse per impostare i valori corretti.

(function () {
    window.currentMouseX = 0;
    window.currentMouseY = 0;

    // Guess the initial mouse position approximately if possible:
    var hoveredElement = document.querySelectorAll(':hover');
    hoveredElement = hoveredElement[hoveredElement.length - 1]; // Get the most specific hovered element

    if (hoveredElement != null) {
        var rect = hoveredElement.getBoundingClientRect();
        // Set the values from hovered element's position
        window.currentMouseX = window.scrollX + rect.x;
        window.currentMouseY = window.scrollY + rect.y;
    }

    // Listen for mouse movements to set the correct values
    document.addEventListener('mousemove', function (e) {
        window.currentMouseX = e.pageX;
        window.currentMouseY = e.pageY;
    });
}())

Fonte CMS Composr : https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff-b162dc9c35a97618a96748639ff41251R1202


0
var x = 0;
var y = 0;

document.addEventListener('mousemove', onMouseMove, false)

function onMouseMove(e){
    x = e.clientX;
    y = e.clientY;
}

function getMouseX() {
    return x;
}

function getMouseY() {
    return y;
}

14
Questo non richiede ancora all'utente di spostare il mouse?
Paul Hiemstra,

0

Penso che potrei avere una soluzione ragionevole senza contare div e pixel..lol

Basta usare il frame di animazione o un intervallo di tempo di una funzione. una volta avrai comunque bisogno di un evento del mouse solo per iniziare, ma tecnicamente lo posizionerai dove preferisci.

Fondamentalmente stiamo monitorando un div fittizio in ogni momento senza il movimento del mouse.

// create a div(#mydiv) 1px by 1px set opacity to 0 & position:absolute;

Di seguito è la logica ..

var x,y;


$('body').mousemove(function( e ) {

    var x = e.clientX - (window.innerWidth / 2);
    var y = e.clientY - (window.innerHeight / 2);
 }


function looping (){

   /* track my div position 60 x 60 seconds!
      with out the mouse after initiation you can still track the dummy div.x & y
      mouse doesn't need to move.*/

   $('#mydiv').x = x;    // css transform x and y to follow 
   $('#mydiv)'.y = y;

   console.log(#mydiv.x etc)

   requestAnimationFrame( looping , frame speed here);
}  
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.