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第二次调用该函数时将没有对象。您可能应该听一些比use更为重要的事件setTimeout
Felix Kling

是的,但是mouse_position()函数不应该每100毫秒调用一次它自己。它实际上不应该像无限递归函数那样工作吗?
哈里


@Titan:是的,但我怀疑它会出错,因为window.event将会是undefinednull。如果没有事件,则没有event对象。
Felix Kling

1
出于兴趣,这有什么用途?
SuperUberDuper '16

Answers:


178

eventmousemove事件处理程序接收到的对象上报告鼠标的位置,您可以将其附加到窗口(事件冒泡):

(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。是的,在现代计算机上似乎不多,但是浏览器中发生了很多事情。因此,例如,您可以跟踪上一个处理的位置,如果位置不正确,则可以立即从处理程序中保释。改变了。


66

这是一个基于jQuery和主体上的鼠标事件侦听器(远优于常规轮询)的解决方案:

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

正如我已经提到的,定期轮询正是我想要做的。我没有跟踪鼠标事件的变化,我只是想每隔x毫秒捕获一次鼠标位置(无论鼠标是否移动)。
哈里

3
为什么跟踪您肯定知道的值没有改变?我不明白,除非是家庭作业问题。使用event方法,您可以跟踪这些值的每次更改,然后如果需要出于任何目的处理这些值,则在其他位置进行100ms轮询。
solendil 2011年

1
除了不必要地使用5mb JS库之外,这里没有使用jQuery的优势
Pattycake Jr

@PattycakeJr我最后一次查看它的缩小版本是在90kB以下
Kris,

1
@PattycakeJr此外,如果你超级都不太可能下载它,如果你指向CDN,因为几乎所有的其他网站链接到它
布赖恩·雷斯曼

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

打开控制台(Ctrl+ Shift+ J),复制粘贴上面的代码,然后在浏览器窗口上移动鼠标。


1
Imo最佳答案
这里

10

我相信我们对此有过多的思考,

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


1
我是该论坛的新手,所以我知道,请解释为什么您-1nd我的遮阳篷-这是为了避免再次犯同样的错误。谢谢!ThePROgrammer
dGRAMOP,2015年

10
我也很生气,没有任何解释。为了给您一个可能的解释,此答案并未解决OP每100 ms轮询一次的问题。在他对其他答案的回答中,很明显这是必要的。
aaaaaa 2015年

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的出色回答,在100ms计时器上完全定义了代码。(他留下了一些想像的细节。)

感谢OP的问题,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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.