核心概念:两种坐标系统
要理解鼠标位置,首先要明白网页中的两种坐标系统:

(图片来源网络,侵删)
-
视口坐标
- 定义:相对于浏览器窗口(或者说,浏览器可视区域)左上角的坐标。
- 特点:当用户滚动页面时,同一个元素在视口中的位置会改变,但它的视口坐标也随之改变,这个坐标不受页面滚动的影响。
- 对应属性:
event.clientX和event.clientY。
-
文档坐标
- 定义:相对于整个 HTML 文档(从
<body>或<html>的左上角开始)的坐标。 - 特点:这是元素的“绝对”位置,即使你滚动页面,一个元素在文档中的坐标也是固定的,这个坐标包含了页面滚动带来的偏移量。
- 对应属性:
event.pageX和event.pageY。
- 定义:相对于整个 HTML 文档(从
简单比喻:
- 视口坐标 就像你在房间里,相对于房间墙壁的位置,你往前走,房间里的家具相对于你的位置就变了。
- 文档坐标 就像家具在整个城市地图上的绝对地址,无论你在房间的哪个角落,家具的地址是不变的。
如何获取鼠标位置
你需要监听鼠标移动事件,通常是 mousemove 事件。

(图片来源网络,侵删)
获取鼠标在视口中的位置 (clientX, clientY)
这是最简单直接的方法,适用于大多数不需要考虑页面滚动的场景,比如拖拽元素、创建跟随鼠标的菜单等。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">获取鼠标位置 (clientX, clientY)</title>
<style>
body {
height: 200vh; /* 为了演示滚动效果,让页面变长 */
font-family: sans-serif;
}
#info {
position: fixed;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="info">
<p>鼠标在视口中的位置:</p>
<p>X: <span id="clientX">0</span></p>
<p>Y: <span id="clientY">0</span></p>
</div>
<script>
// 获取显示位置的元素
const clientXSpan = document.getElementById('clientX');
const clientYSpan = document.getElementById('clientY');
// 为整个文档添加 mousemove 事件监听器
document.addEventListener('mousemove', (event) => {
// event.clientX 和 event.clientY 提供了相对于视口的坐标
clientXSpan.textContent = event.clientX;
clientYSpan.textContent = event.clientY;
});
</script>
</body>
</html>
说明:
document.addEventListener('mousemove', ...)会在鼠标在页面的任何位置移动时触发回调函数。event对象是事件对象,包含了关于事件的详细信息,其中就包括鼠标坐标。event.clientX是鼠标在视口中的 X 坐标。event.clientY是鼠标在视口中的 Y 坐标。
获取鼠标在文档中的位置 (pageX, pageY)
当你需要获取鼠标在页面“绝对”位置时,应该使用 pageX 和 pageY,这在实现全页面交互、绘制 Canvas、或者需要精确计算元素相对于文档位置的场景中非常有用。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">获取鼠标位置 (pageX, pageY)</title>
<style>
body {
height: 200vh; /* 为了演示滚动效果 */
font-family: sans-serif;
}
#info {
position: fixed;
top: 10px;
right: 10px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="info">
<p>鼠标在文档中的位置:</p>
<p>X: <span id="pageX">0</span></p>
<p>Y: <span id="pageY">0</span></p>
</div>
<script>
// 获取显示位置的元素
const pageXSpan = document.getElementById('pageX');
const pageYSpan = document.getElementById('pageY');
// 为整个文档添加 mousemove 事件监听器
document.addEventListener('mousemove', (event) => {
// event.pageX 和 event.pageY 提供了相对于文档的坐标
pageXSpan.textContent = event.pageX;
pageYSpan.textContent = event.pageY;
});
</script>
</body>
</html>
说明:
event.pageX是鼠标在文档中的 X 坐标。event.pageY是鼠标在文档中的 Y 坐标。- 注意:当你滚动页面时,即使鼠标在视口中的位置不变,
pageX和pageY的值也会随着滚动而增加。
重要注意事项
pageX 和 pageY 的兼容性
pageX 和 pageY 在所有现代浏览器(Chrome, Firefox, Safari, Edge)中都得到了很好的支持,但在一些非常旧的浏览器(如 IE8 及更早版本)中可能不被支持。
如果你的项目需要兼容这些旧浏览器,可以手动计算 pageX 和 pageY:
// 兼容旧浏览器的写法 let x = event.clientX + window.scrollX; let y = event.clientY + window.scrollY; // 或者使用 event.pageX 和 event.pageY,如果不存在则用上面的计算方式 let x = event.pageX || (event.clientX + window.scrollX); let y = event.pageY || (event.clientY + window.scrollY);
window.scrollX和window.scrollY获取页面水平和垂直方向的滚动距离。
监听事件的目标
上面的例子中,我们在 document 上监听了 mousemove 事件,这意味着只要鼠标在浏览器窗口内移动,事件就会被触发。
如果你只想在某个特定的元素上跟踪鼠标,你应该在该元素上添加事件监听器:
<div id="myBox" style="width: 300px; height: 200px; background: lightblue; margin: 50px;">
将鼠标移动到这里
</div>
<script>
const myBox = document.getElementById('myBox');
myBox.addEventListener('mousemove', (event) => {
// 这里的坐标是相对于 myBox 这个元素的左上角
console.log(`相对于 myBox 的 X: ${event.offsetX}, Y: ${event.offsetY}`);
console.log(`相对于视口的 X: ${event.clientX}, Y: ${event.clientY}`);
});
</script>
这里出现了另一个有用的属性:
offsetX/offsetY:返回鼠标事件发生的位置相对于目标元素的坐标,这在处理特定元素的交互时非常有用。
总结与对比
| 属性 | 坐标系统 | 描述 | 是否受页面滚动影响 | 兼容性 |
|---|---|---|---|---|
clientX |
视口 | 相对于浏览器窗口左上角。 | 否 | 优秀 |
clientY |
视口 | 相对于浏览器窗口左上角。 | 否 | 优秀 |
pageX |
文档 | 相对于整个文档的左上角。 | 是 | 良好 (IE9+) |
pageY |
文档 | 相对于整个文档的左上角。 | 是 | 良好 (IE9+) |
offsetX |
目标元素 | 相对于事件目标元素的内边距边缘。 | 否 | 良好 (IE9+) |
offsetY |
目标元素 | 相对于事件目标元素的内边距边缘。 | 否 | 良好 (IE9+) |
如何选择?
- 创建跟随鼠标的 UI(如工具提示、自定义光标):使用
clientX和clientY,因为它们不受滚动影响,定位更稳定。 - 在 Canvas 或 SVG 上绘图:使用
pageX和pageY,因为画布是文档的一部分,你需要知道它在文档中的绝对位置。 - 处理特定元素的拖拽或点击区域:使用
offsetX和offsetY,可以轻松知道点击发生在元素内部的哪个位置。
希望这个详细的解释能帮助你完全理解在 JavaScript 中获取鼠标位置的各种方法!
