Javascript - Fare konumunu izleme


161

Fare imlecinin konumunu, her t saniyede bir periyodik olarak izlemeyi umuyorum. Bu nedenle, bir sayfa yüklendiğinde - bu izleyici başlamalı ve (her 100 ms'de bir), posX ve posY'nin yeni değerini almalı ve formda yazdırmalıyım.

Aşağıdaki kodu denedim - ancak değerler yenilenmiyor - form kutularında yalnızca posX ve posY değerleri görünür. Bunu nasıl başlatabileceğim hakkında bir fikrin var mı?

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

Sorun, eventişlev ikinci kez çağrıldığında hiçbir nesne olmayacak olmasıdır . Muhtemelen kullanmaktan başka bir olay dinlemelisiniz setTimeout.
Felix Kling

Evet, ancak mouse_position () işlevi her 100 milisaniyede bir kendini çağırmaya devam etmemelidir. Aslında sonsuz bir özyinelemeli işlev gibi davranmamalı mı?
Hari


@Titan: Evet, ancak hata olacağından şüpheleniyorum ya da window.eventolacak . Etkinlik yoksa, nesne yoktur . undefinednullevent
Felix Kling

1
ilgisiz, bunun uygulaması nedir?
SuperUberDuper

Yanıtlar:


178

Farenin konumu, olay eventiçin bir işleyici tarafından alınan nesneye bildirilir mousemoveve pencereye ekleyebilirsiniz (olay balonları):

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

(Bunun gövdesinin ifyalnızca eski IE'de çalışacağını unutmayın.)

Yukarıdaki eylem örneği - farenizi sayfanın üzerine sürüklerken noktalar çizer. (IE8, IE11, Firefox 30, Chrome 38'de test edilmiştir.)

Zamanlayıcı tabanlı bir çözüme gerçekten ihtiyacınız varsa, bunu bazı durum değişkenleriyle birleştirirsiniz:

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

Bildiğim kadarıyla, bir olay görmeden fare konumunu alamazsınız, başka bir Yığın Taşması sorusuna bu cevabın onayladığı bir şey.

Yan not : Her 100 ms'de (10 kez / saniye) bir şey yapacaksanız, bu işlevde yaptığınız gerçek işlemi çok, çok sınırlı tutmaya çalışın . Bu, özellikle eski Microsoft tarayıcıları için çok fazla iş. Evet, modern bilgisayarlarda çok fazla görünmüyor, ancak tarayıcılarda çok şey oluyor ... Yani, örneğin, işlediğiniz son pozisyonu takip edebilir ve pozisyon yoksa, işleyiciden hemen kurtulabilirsiniz. t değişti.


66

İşte jQuery ve vücuttaki bir fare olay dinleyicisine (normal bir yoklamadan çok daha iyi) dayanan bir çözüm:

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

Bahsettiğim gibi, düzenli oylama tam olarak yapmak istediğim şey. Fare olaylarındaki değişiklikleri izlemiyorum, sadece fare konumunu her x milisaniyede (farenin hareket edip etmediğine bakılmaksızın) yakalamak istiyorum.
Hari

3
Kesinlikle bildiğiniz bir değeri izlemek neden değişmedi? Bir ev ödevi sorunu olmadıkça anlamıyorum. Olay yöntemiyle, bu değerlerin her değişikliğini takip edebilir, daha sonra bu değerleri herhangi bir amaç için işlemeniz gerekiyorsa başka bir yerde 100ms yoklama yapabilirsiniz.
solendil

1
Gereksiz yere
5mb

@PattycakeJr En son baktığımda küçültülmüş versiyonda 90 kb'nin altındaydı
Kris

1
@PattycakeJr siz de hemen hemen her site ona bağlandığı için bir süper
Brian Leishman

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

Konsolunuzu açın ( Ctrl+ Shift+ J), yukarıdaki kodu kopyalayıp yapıştırın ve farenizi tarayıcı penceresinde hareket ettirin.


1
Imo en iyi cevap
Here Here

10

İnanıyorum ki, bunu düşünüyoruz,

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


1
Bu forumda yeniyim, bu yüzden biliyorum ki, lütfen neden uyandığımı açıklayın - bu yüzden aynı hatayı tekrar yapmıyorum. Teşekkürler! ThePROgrammer
dGRAMOP

10
Ben de açıklama olmadan downvotes rahatsız olsun. Size olası bir açıklama yapmak için, bu cevap OP'nin her 100 ms'de bir yoklama sorununu ele almaz. Diğer cevaplara verdiği yanıtta bunun bir zorunluluk olduğu daha açıktır.
aaaaaa

1
Ayrıca bu tür satır içi olay işlemenin kullanımdan kaldırıldığına inanıyorum. document.body.addEventListener("mousemove", function (e) {})HTML kodunun aksine javascript kodunuzda bunu yapmanın yolu
Ryan

10

Sadece imlecin X / Y pozisyonlarını bilmek istediğini düşündüğüm cevap neden bu kadar karmaşık.

// 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 tabanlı kod:

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

document.addEventListener('mousemove', handleMousemove);

Fareyi kaldırmak için kısıtlamaya ihtiyacınız varsa, bunu kullanın:

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

işte örnek


2

Tarayıcıdan bağımsız olarak, aşağıdaki satırlar doğru fare konumunu almam için çalıştı.

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


2

Fare hareketini görsel olarak izlemek istiyorsanız:

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

Bir yorum yanıtı yayınlamak için yeterli üne sahip değilim, ancak TJ Crowder'ın mükemmel cevabını aldım ve kodu 100ms'lik bir zamanlayıcıda tam olarak tanımladım . (Hayal gücüne bazı detaylar bıraktı.)

Soru için OP ve cevap için TJ teşekkürler! İkiniz de çok yardımcısınız. Kod aşağıda bir isbin aynası olarak gömülüdür.

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

İşte iki gereksinimin bir kombinasyonu: her 100 milisaniyede bir fare konumunu izleyin:

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

Bu, fare konumunu izler ve etki eder, ancak yalnızca her periyot milisaniyedir.


0

@TJ Crowder ve @RegarBoy'un cevaplarının basitleştirilmiş bir versiyonu .

Bence daha azı daha fazla.

Etkinlik hakkında daha fazla bilgi için onmousemove etkinliğine göz atın .

Görüntü fare izleyici

Yeni bir değeri var posXve posYher zaman yatay ve dikey koordinatlarına göre fare hareket eder.

<!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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.