Javascript - відстежуйте положення миші


161

Я сподіваюсь відстежувати положення курсору миші періодично кожні t мсекунди. Тож по суті, коли сторінка завантажується - цей трекер повинен запускатися і, скажімо, кожні 100 мс, я повинен отримати нове значення posX і posY та роздрукувати його у формі.

Я спробував наступний код - але значення не оновлюються - у полях форм відображаються лише початкові значення posX та posY. Будь-які ідеї про те, як я можу це зробити і працювати?

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

Проблема полягає в тому, що eventоб'єкта не буде, коли функція буде викликана вдруге. Напевно, вам слід слухати якусь подію, ніж використовувати setTimeout.
Фелікс Клінг

Так, але чи не повинна функція mouse_position () продовжувати телефонувати кожні 100 мілісекунд. Чи не слід насправді вести себе як нескінченна рекурсивна функція?
Харі


@Titan: Так, але я підозрюю , що це буде помилка , тому що window.eventбуде undefinedабо null. Якщо події немає, eventоб’єкта немає .
Фелікс Клінг

1
з інтересу, що це за застосування?
SuperUberDuper

Відповіді:


178

Положення миші повідомляється про eventоб'єкт, отриманий обробником для mousemoveподії, який ви можете прикріпити до вікна (бульбашки події):

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

(Зверніть увагу, що тіло цього ifзапускається лише на старому IE.)

Приклад вищезазначеного в дії - він малює точки під час перетягування миші по сторінці. (Тестовано на IE8, IE11, Firefox 30, Chrome 38.)

Якщо вам дійсно потрібне рішення, засноване на таймері, ви поєднуєте це з деякими змінними стану:

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

Наскільки мені відомо, ви не можете отримати позицію миші, не побачивши події, що, як видається, підтверджує цю відповідь на інше запитання про переповнення стека .

Побічна примітка : Якщо ви збираєтесь робити що-небудь кожні 100 мс (10 разів / секунду), намагайтеся зберегти фактичну обробку, яку ви виконуєте в цій функції, дуже і дуже обмежено . Це дуже багато роботи для браузера, особливо для старих Microsoft. Так, на сучасних комп’ютерах це здається не так вже й багато, але в браузерах багато що відбувається, тож, наприклад, ви можете відслідковувати останню оброблювану вами позицію і негайно відмовлятися від обробника, якщо позиція не є ' t змінився.


66

Ось рішення на основі jQuery та слухача подій миші (що набагато краще, ніж звичайне опитування) на тілі:

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

Як я вже згадував, регулярне опитування - саме те, що я хочу зробити. Я не відстежую зміни в подіях миші, я лише прагну зафіксувати положення миші кожні х мілісекунд (незалежно від того, рухалася миша чи ні).
Харі

3
Чому відстеження значення, яке ви точно знаєте, не змінилося? Я не розумію, якщо це не домашня робота. За допомогою методу події ви можете відстежувати кожну зміну цих значень, а потім робити опитування на 100 м в іншому місці, якщо вам потрібно обробляти ці значення з будь-якою метою.
solendil

1
Тут немає переваги використання jQuery, за винятком зайвого використання лінійки JS
Pattycake Jr

@PattycakeJr Востаннє, коли я подивився, це було менше 90 кБ у мінімізованій версії
Kris

1
@PattycakeJr також , якщо ви супер навряд чи завантаження його взагалі , якщо ви вказати на CDN , так як майже всі інші посилання сайту до нього
Брайан Leishman

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

Відкрийте консоль ( Ctrl+ Shift+ J), скопіюйте і вставте код вище та перемістіть мишу у вікні браузера.


1
Я найкраща відповідь
Ось

10

Я вважаю, що ми переосмислюємо це,

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


1
Я новачок на цьому форумі, так що я просто знаю, поясніть, будь ласка, чому ви - мій тент - це так, що я не хочу повторювати ту саму помилку. Дякую! ThePROgrammer
dGRAMOP

10
Мене теж дратують грохоти без пояснень. Щоб дати вам можливе пояснення, ця відповідь не стосується проблеми ОП щодо опитування кожні 100 мс. У його відповіді на інші відповіді ясніше, що це необхідність.
aaaaaa

1
також я вважаю, що подібне оброблення подій в режимі вбудованої системи застаріле. document.body.addEventListener("mousemove", function (e) {})це зробити це у вашому коді JavaScript на відміну від html
Ryan

10

Я думаю, що він хоче лише знати X / Y позиції курсору, ніж чому відповідь настільки складна.

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

Код на основі ES6:

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

document.addEventListener('mousemove', handleMousemove);

Якщо вам потрібно дроселювання для переміщення миші, скористайтеся цим:

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

ось приклад


2

Незалежно від браузера, нижче рядки працювали для мене, щоб отримати правильне положення миші.

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


2

Якщо ви просто хочете візуально відстежувати рух миші:

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

У мене недостатньо репутації, щоб розмістити коментар, але я взяв чудову відповідь TJ Crowder і повністю визначив код на таймері 100 мс . (Він залишив деякі подробиці уяві.)

Дякую ОП за запитання, а TJ за відповідь! Ви обоє чудова допомога. Код вбудований нижче як дзеркало 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

Ось поєднання двох вимог: відстежуйте положення миші кожні 100 мілісекунд:

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

Він відслідковує та діє на позиції миші, але лише кожен період мілісекунд.


0

Просто спрощена версія відповідей @TJ Crowder та @RegarBoy .

Менше на мою думку більше.

Перегляньте подію onmousemove, щоб отримати додаткову інформацію про подію.

Зображення миші трекер

Там в нове значення , posXі posYкожен раз , коли миша рухається в відповідно до горизонтальними і вертикальними координатами.

<!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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.