HOWTO · JavaScript

在 JavaScript 中跟踪鼠标位置

在本教程中,我们将了解如何在 JavaScript 中使用鼠标事件跟踪鼠标位置。

本页内容

为跟踪指针移动,可以为浏览器的 mousemove 事件注册回调。回调会接收一个 MouseEvent;应从该事件读取坐标属性,而不是另外维护指针状态。指针在窗口中移动时会触发此事件,因此处理函数可以在每次移动时读取最新位置。

监听鼠标移动事件 mousemove

事件监听器由事件类型和回调函数组成。在下面的浏览器示例中,window.addEventListener 会为 mousemove 注册 handleMouseMove,回调读取 pageX、pageY、clientX 和 clientY。属性名称区分大小写。mousemove 事件用于报告指针移动;页面加载或指针静止时都不会因此触发该事件。

下面的小型可运行示例展示了回调如何格式化事件值。示例中的普通对象只是用于说明属性名称的样例输入;在交互式页面中应使用浏览器提供的真实 MouseEvent。代码中的控制台标签保持英文原样,以便与示例输出对应。

运行此示例:

本节中的代码以及显示的标签或输出仍为英文。

function handleMouseMove(event) {
  console.log(
    `page: (${event.pageX}, ${event.pageY}); client: (${event.clientX}, ${event.clientY})`
  );
}

handleMouseMove({ pageX: 120, pageY: 240, clientX: 120, clientY: 240 });

要体验浏览器中的交互,请使用这个独立页面。页面内容足够长,可以滚动;指针在页面上移动时,处理函数会记录两组坐标。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Mouse coordinates</title>
  <style>
    body { min-height: 1600px; font: 16px sans-serif; }
    main { padding: 2rem; }
  </style>
</head>
<body>
  <main>
    <h1>Move the pointer, then scroll</h1>
    <p>Open the browser developer console to compare the coordinate pairs.</p>
  </main>
  <script>
    window.addEventListener('mousemove', (event) => {
      console.log(
        `page: (${event.pageX}, ${event.pageY}); client: (${event.clientX}, ${event.clientY})`
      );
    });
  </script>
</body>
</html>

如何选择页面坐标或视口坐标

pageX 和 pageY 以文档左上角为原点测量指针位置。它们包含文档的滚动偏移量,因此适合在读者滚动页面时仍需让位置对应文档内容的场景。例如,记录长文档中某个点的位置时,可以使用页面坐标。

clientX 和 clientY 以当前可见视口的左上角为原点进行测量。滚动不会改变这个原点。如果要定位或比较当前浏览器可见区域内的对象,例如自定义光标标记或视口叠加层,可以使用这组值。

这两组坐标属于不同的坐标空间,因此计算时应始终使用同一组。混用页面坐标和视口坐标会使结果产生与滚动偏移量相对应的位移。若要让某个元素跟随指针,还需要额外处理鼠标事件并编写元素定位逻辑;仅仅读取坐标不会移动元素。

滚动时比较 pageX 和 clientX

滚动前,文档原点与视口原点重合,因此水平坐标 pageX 和 clientX 相同,垂直坐标 pageY 和 clientY 也相同。移动指针并在控制台中查看两组坐标。第一张随附视图展示了滚动前的控制台。

浏览器开发者控制台显示滚动前的页面坐标和视口坐标

向下滚动后,水平坐标通常仍然一致;垂直坐标 pageY 会包含滚动距离,而 clientY 仍以视口顶部为基准。两者的差值对应当前的滚动偏移量。第二张随附视图展示了滚动后的控制台。

浏览器开发者控制台显示滚动后不同的 pageY 和 clientY 值

如果要获取相对于当前可见区域的位置,请使用 clientX 和 clientY。如果要获取相对于文档的位置(包括滚动后的内容),请使用 pageX 和 pageY。如需了解更多浏览器鼠标事件,请参阅 MDN 鼠标事件参考。