Javascript - Suivi de la position de la souris


161

J'espère suivre la position du curseur de la souris, périodiquement toutes les t msecondes. Donc, essentiellement, lorsqu'une page se charge - ce tracker devrait démarrer et pendant (disons) toutes les 100 ms, je devrais obtenir la nouvelle valeur de posX et posY et l'imprimer sous la forme.

J'ai essayé le code suivant - mais les valeurs ne sont pas actualisées - seules les valeurs initiales de posX et posY apparaissent dans les boîtes de formulaire. Avez-vous des idées sur la façon dont je peux le faire fonctionner?

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

Le problème est qu'il n'y aura pas d' eventobjet lorsque la fonction est appelée pour la deuxième fois. Vous devriez probablement écouter un événement plutôt que de l'utiliser setTimeout.
Felix Kling

Oui, mais la fonction mouse_position () ne devrait-elle pas continuer à s'appeler toutes les 100 millisecondes. Ne devrait-il pas réellement se comporter comme une fonction récursive infinie?
Hari

2

@Titan: Oui, mais je soupçonne que ce sera une erreur parce que ce window.eventsera undefinedou null. S'il n'y a pas d'événement, il n'y a pas d' eventobjet.
Felix Kling

1
par intérêt, quelle en est l’application?
SuperUberDuper

Réponses:


178

La position de la souris est reportée sur l' eventobjet reçu par un gestionnaire pour l' mousemoveévénement, que vous pouvez attacher à la fenêtre (les bulles d'événement):

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

(Notez que le corps de celui- ifci ne fonctionnera que sur l'ancien IE.)

Exemple de ce qui précède en action - il dessine des points lorsque vous faites glisser votre souris sur la page. (Testé sur IE8, IE11, Firefox 30, Chrome 38.)

Si vous avez vraiment besoin d'une solution basée sur une minuterie, combinez-la avec certaines variables d'état:

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

Autant que je sache, vous ne pouvez pas obtenir la position de la souris sans avoir vu un événement, ce que cette réponse à une autre question de Stack Overflow semble confirmer.

Remarque : si vous comptez faire quelque chose toutes les 100 ms (10 fois / seconde), essayez de conserver le traitement que vous effectuez dans cette fonction très, très limitée . C'est beaucoup de travail pour le navigateur, en particulier les anciens Microsoft. Oui, sur les ordinateurs modernes, cela ne semble pas beaucoup, mais il se passe beaucoup de choses dans les navigateurs ... Ainsi, par exemple, vous pouvez garder une trace de la dernière position que vous avez traitée et libérer immédiatement le gestionnaire si la position n'a pas t changé.


66

Voici une solution, basée sur jQuery et un écouteur d'événement de souris (qui est bien meilleur qu'un sondage régulier) sur le corps:

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

Comme je l'ai mentionné, le scrutin régulier est exactement ce que je veux faire. Je ne suis pas en train de suivre les changements dans les événements de la souris, je cherche uniquement à capturer la position de la souris toutes les x millisecondes (que la souris soit déplacée ou non).
Hari

3
Pourquoi suivre une valeur dont vous savez à coup sûr qu'elle n'a pas changé? Je ne comprends pas, sauf si c'est un problème de devoirs. Avec la méthode événementielle, vous pouvez suivre chaque changement de ces valeurs, puis effectuer une interrogation de 100 ms ailleurs si vous devez gérer ces valeurs dans un but quelconque.
solendil

1
Il n'y a aucun avantage à utiliser jQuery ici sauf en utilisant inutilement une librairie JS
Mo

@PattycakeJr La dernière fois que j'ai regardé, il faisait moins de 90 Ko dans la version minifiée
Kris

1
@PattycakeJr aussi si vous êtes super improbable de le télécharger du tout si vous pointez vers un CDN puisque presque tous les autres sites y renvoient
Brian Leishman

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

Ouvrez votre console ( Ctrl+ Shift+ J), copiez-collez le code ci-dessus et déplacez votre souris sur la fenêtre du navigateur.


1
Imo la meilleure réponse
HereHere

10

Je crois que nous y réfléchissons trop,

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


1
Je suis nouveau sur ce forum, donc juste pour que je sache, veuillez expliquer pourquoi vous -1nd mon awnser - c'est pour que je ne fasse plus la même erreur. Merci! ThePROgrammer
dGRAMOP

10
Moi aussi, je suis agacé par les votes négatifs sans explication. Pour vous donner une explication possible, cette réponse ne résout pas le problème de l'OP d'interroger toutes les 100 ms. Il est plus clair dans sa réponse à d’autres réponses que c’est une nécessité.
aaaaaa

1
aussi ce genre de gestion d'événements en ligne est obsolète je crois. document.body.addEventListener("mousemove", function (e) {})est le moyen de le faire, dans votre code javascript par opposition à dans le html
Ryan

10

Ce que je pense qu'il veut seulement connaître les positions X / Y du curseur que pourquoi la réponse est si compliquée.

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

Code basé sur ES6:

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

document.addEventListener('mousemove', handleMousemove);

Si vous avez besoin d'une limitation pour le déplacement de la souris, utilisez ceci:

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

voici un exemple


2

Indépendamment du navigateur, les lignes ci-dessous ont fonctionné pour moi pour récupérer la position correcte de la souris.

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


2

Si vous souhaitez simplement suivre visuellement le mouvement de la souris:

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

Je n'ai pas assez de réputation pour publier une réponse à un commentaire, mais j'ai pris l' excellente réponse de TJ Crowder et j'ai entièrement défini le code sur un minuteur de 100 ms . (Il a laissé quelques détails à l'imagination.)

Merci OP pour la question et TJ pour la réponse! Vous êtes tous les deux d'une grande aide. Le code est intégré ci-dessous en tant que miroir d'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

Voici une combinaison des deux exigences: suivre la position de la souris, toutes les 100 millisecondes:

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

Cela suit et agit sur la position de la souris, mais seulement toutes les millisecondes de période .


0

Juste une version simplifiée des réponses de @TJ Crowder et @RegarBoy .

Moins c'est mieux à mon avis.

Consultez l' événement onmousemove pour plus d'informations sur l'événement.

Suivi de la souris d'image

Il y a une nouvelle valeur de posXet à posYchaque fois que la souris se déplace en fonction des coordonnées horizontales et 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>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.