Javascript - Rastrear posição do mouse

160

Espero rastrear a posição do cursor do mouse, periodicamente a cada t segundos. Então, essencialmente, quando uma página é carregada - esse rastreador deve iniciar e, a cada 100 ms, devo obter o novo valor de posX e posY e imprimi-lo no formulário.

Eu tentei o código a seguir - mas os valores não são atualizados - apenas os valores iniciais de posX e posY aparecem nas caixas de formulário. Alguma idéia de como eu posso colocar isso em funcionamento?

<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>
Hari
fonte
O problema é que não haverá eventobjeto quando a função for chamada pela segunda vez. Você provavelmente deve ouvir algum evento do que usar setTimeout.
Felix Kling
Sim, mas a função mouse_position () não deve continuar se chamando a cada 100 milissegundos. Na verdade, não deveria se comportar como uma função recursiva infinita?
Hari
2
possível duplicado da posição do mouse captura em setInterval () em JavaScript
Assistente de Sombra é ouvido para Você
@Titan: Sim, mas desconfio que ocorrerá um erro porque window.eventserá undefinedou null. Se não houver evento, não há eventobjeto.
Felix Kling
1
por interesse, qual é a aplicação disso?
SuperUberDuper

Respostas:

178

A posição do mouse é relatada no eventobjeto recebido por um manipulador para o mousemoveevento, que você pode anexar à janela (as bolhas de eventos):

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

(Observe que o corpo disso ifserá executado apenas no IE antigo.)

Exemplo do acima em ação - ele desenha pontos à medida que você arrasta o mouse sobre a página. (Testado no IE8, IE11, Firefox 30, Chrome 38.)

Se você realmente precisa de uma solução baseada em timer, combine isso com algumas variáveis ​​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
        }
    }
})();

Tanto quanto sei, você não pode obter a posição do mouse sem ter visto um evento, algo que esta resposta a outra pergunta do Stack Overflow parece confirmar.

Nota : Se você fizer algo a cada 100 ms (10 vezes / segundo), tente manter o processamento real que você faz nessa função muito, muito limitado . Isso dá muito trabalho para o navegador, principalmente os mais antigos da Microsoft. Sim, em computadores modernos, isso não parece muito, mas há muita coisa acontecendo nos navegadores ... Por exemplo, você pode acompanhar a última posição processada e resgatar o manipulador imediatamente se a posição não tiver ' t mudou.

TJ Crowder
fonte
66

Aqui está uma solução, baseada no jQuery e em um ouvinte de evento do mouse (que é muito melhor do que uma pesquisa regular) no corpo:

$("body").mousemove(function(e) {
    document.Form1.posx.value = e.pageX;
    document.Form1.posy.value = e.pageY;
})
solendil
fonte
Como eu mencionei, a pesquisa regular é exatamente o que eu quero fazer. Não estou rastreando alterações nos eventos do mouse, só estou procurando capturar a posição do mouse a cada x milissegundos (independentemente de o mouse se mover ou não).
Hari
3
Por que rastrear um valor que você sabe com certeza não mudou? Eu não entendo, a menos que seja um problema de lição de casa. Com o método de evento, você pode rastrear todas as alterações desses valores e, em seguida, realizar uma pesquisa de 100ms em outro local, se precisar manipular esses valores para qualquer finalidade.
solendil
1
Não há vantagem de usar jQuery aqui, exceto desnecessariamente usando um 5MB JS lib
Pattycake Jr
@PattycakeJr A última vez que eu olhei foi sob 90KB na versão minified
Kris
1
@PattycakeJr também se você é super improvável baixá-lo em tudo se você apontar para um CDN já que quase todos os outros links de site para isso
Brian Leishman
53
onmousemove = function(e){console.log("mouse location:", e.clientX, e.clientY)}

Abra seu console ( Ctrl+ Shift+ J), copie e cole o código acima e mova o mouse na janela do navegador.

RegarBoy
fonte
1
Imo a melhor resposta
AquiAqui
10

Eu acredito que estamos pensando demais nisso,

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

dGRAMOP
fonte
1
Sou novo neste fórum, então só para que eu saiba, por favor, explique por que você encontra o meu awnser - isso é para que eu não cometa o mesmo erro novamente. Obrigado! ThePROgrammer
dGRAMOP /
10
Eu também fico irritado com votos negativos sem explicação. Para lhe dar uma explicação possível, esta resposta não aborda o problema do OP de pesquisar a cada 100 ms. É mais claro em sua resposta a outras respostas que isso é uma necessidade.
Aaaaaa
1
também esse tipo de manipulação de eventos em linha está obsoleto, acredito. document.body.addEventListener("mousemove", function (e) {})é a maneira de fazer isso, em seu código javascript ao invés de no html
Ryan
10

O que eu acho que ele só quer saber as posições X / Y do cursor do que por que a resposta é tão 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>

Murtaza
fonte
5

Código baseado no ES6:

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

document.addEventListener('mousemove', handleMousemove);

Se você precisar de limitação para mover o mouse, use o seguinte:

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

aqui está um exemplo

oboshto
fonte
2

Independentemente do navegador, as linhas abaixo trabalharam para eu buscar a posição correta do mouse.

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

Sai Ganesh Pittala
fonte
2

Se você quiser apenas acompanhar o movimento do 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>

luistar15
fonte
2

Não tenho reputação suficiente para postar uma resposta a um comentário, mas peguei a excelente resposta de TJ Crowder e defini completamente o código em um temporizador de 100 ms . (Ele deixou alguns detalhes para a imaginação.)

Obrigado OP pela pergunta e TJ pela resposta! Vocês dois são uma grande ajuda. O código é incorporado abaixo como um espelho 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>

Kris com um K
fonte
0

Aqui está uma combinação dos dois requisitos: rastreie a posição do mouse, a cada 100 milissegundos:

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

Isso rastreia e age na posição do mouse, mas apenas a cada período de milissegundos.

Bobby Jack
fonte
0

Apenas uma versão simplificada das respostas de @TJ Crowder e @RegarBoy .

Menos é mais na minha opinião.

Confira o evento onmousemove para obter mais informações sobre o evento.

Rastreador de mouse de imagem

Há um novo valor de posXe posYtoda vez que o mouse se move de acordo com as coordenadas horizontal e vertical.

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