JavaScript 坐标与距离计算完全指南:Window、Element 及 MouseEvent

作者:像素猫

时间:2026-10-23

浏览:595

本文系统梳理 JavaScript 中坐标与距离计算的核心 API。涵盖 window 对象的视口与滚动属性,Element 节点的 client、scroll、offset 系列尺寸差异,以及 MouseEvent 接口中 clientX、screenX、offsetX 等鼠标位置属性的具体含义与计算基准,帮助开发者精准定位与布局。

文章目录

前言与概述

一 前言

在前端开发实践中,计算坐标和距离是高频需求。由于涉及的属性和方法繁多,全部记忆并不现实,通常只能临时查阅。为此,本文对相关知识进行整理与归纳,旨在加深理解并方便随时检索,提高开发效率。

Window 对象的坐标与滚动属性

二 window 对象

在浏览器环境中,window 对象(注意首字母小写)代表当前的浏览器窗口。它是当前页面的顶层对象,即最高层级的对象,所有其他对象均隶属于它。若变量未显式声明,则默认作为顶层对象的属性存在。摘自《阮一峰 JavaScript 教程》

位置大小属性

window.screenX , window.screenY

只读属性

该属性返回浏览器窗口左上角相对于当前屏幕左上角的水平距离和垂直距离,单位为像素。

window.innerHeight , window.innerWidth

只读属性

返回网页在当前窗口中可见区域的高度和宽度,即「视口」(viewport)的大小,单位为像素。

需注意,这两个属性返回的数值包含了滚动条的高度和宽度。

window.outerHeight , window.outerWidth

只读属性

返回浏览器窗口的高度和宽度,计算范围包括浏览器菜单和边框,单位为像素。

window.scrollX , window.scrollY

只读属性

别名: window.pageXOffset , window.pageYOffset

分别返回页面的水平滚动距离和垂直滚动距离,单位均为像素。

需注意,这两个属性的返回值并非整数,而是双精度浮点数。若页面未发生滚动,其值为 0。

摘自《阮一峰 JavaScript 教程》

为确保跨浏览器兼容性,建议使用 window.pageXOffset 替代 window.scrollX。此外,旧版本 IE(低于 9 版本)不支持这两个属性,需通过其他非标准属性解决兼容性问题。

摘自 MDN :https://developer.mozilla.org/zh-CN/docs/Web/API/Window/scrollX

window 对象的方法

window.scrollTo() , window.scroll() , window.scrollBy()

window.scrollTo 方法 ---> 别名: window.scroll 方法

用于将文档滚动至指定位置。

该方法接受两个参数,分别表示滚动后位于窗口左上角的页面坐标。

此外,该方法也可接受一个配置对象作为参数。

window.scrollTo(options)

配置对象 options 包含三个属性。

  • top:滚动后页面左上角的垂直坐标,即 y 坐标。
  • left:滚动后页面左上角的水平坐标,即 x 坐标。
  • behavior:字符串,表示滚动的方式,可选值包括 smooth、instant、auto,默认值为 auto。

window.scrollBy 方法用于将网页滚动指定的距离(单位为像素)。

它接受两个参数:水平向右滚动的像素数和垂直向下滚动的像素数。

注意:请仔细体会 scrollTo 与 scrollBy 这两者的区别。

Element 节点尺寸与位置计算

三 Element 节点

Element 节点对象对应网页中的 HTML 元素。每一个 HTML 元素在 DOM 树上都会转化为一个 Element 节点对象(简称元素节点)。

相关属性

Element.clientHeight,Element.clientWidth

分别返回元素的高度和宽度,返回值始终为整数值。

若该元素为内联元素(display: inline;),则返回值为 0。

从盒模型角度而言,返回的数值计算包含元素的 content 和 padding,但不包括 border 和 margin。

若存在滚动条,返回的数值会减去滚动条占据的宽度或高度(即不包含滚动条在内)。


// 浏览器视口高度
document.documentElement.clientHeight
// 网页总高度
document.body.clientHeight

Element.clientLeft,Element.clientTop

分别返回元素的左边框宽度和上边框宽度,若无边框则返回 0。

同样不支持内联元素。

(我对这两个属性的具体应用场景尚不明确……)

Element.scrollHeight,Element.scrollWidth

返回当前元素的总高度和总宽度,包括溢出容器、当前不可见的部分。

包含 padding 区域。

包含伪元素的宽度和高度。

不包含滚动条的宽度和高度。

以下通过一个小 demo 辅助理解:


<div class="box"> 666 </div>
.box {
width: 200px; height: 200px; overflow: hidden;
border: 1px solid red; padding: 10px; position: relative;
}
.box::after {
position: absolute; content: '';
width: 100px; height: 100px; left: 100%;
}
let box = document.querySelector('.box')
console.log(box.scrollWidth) // 320
console.log(box.scrollHeight) // 220

可以看到 box 元素的 scrollHeight 是 220,这与我们提到的「包括 padding 区域」相符合。

那 box 元素的 scrollWidth 为何是 320 ?这是因为伪元素的位置和宽度所致,尽管伪元素溢出被隐藏,但该属性返回的数值依然包括它。

当然,不仅包括其宽度和高度,其所处的位置也会计算在内。

例如将伪元素的 css 修改如下:


.box::after {
position: absolute; content: '';
width: 100px; height: 100px;
left: 120%; top: 120%;
}

现在你是否能猜出 box 的 scrollWidth 和 scrollHeight 分别是多少?

Element.scrollLeft,Element.scrollTop

可读写,设置该属性的值,会导致浏览器将当前元素自动滚动到相应的位置。

分别返回当前元素的水平滚动距离和垂直滚动距离。

对于那些没有滚动条的网页元素,这两个属性总是等于 0。

若要查看整张网页的水平滚动距离和垂直滚动距离,需从 document.documentElement 元素上读取。


document.documentElement.scrollLeft
document.documentElement.scrollTop

Element.offsetHeight,Element.offsetWidth

分别返回元素的高度和宽度,包括元素本身的高和宽、padding 和 border,以及滚动条的高和宽。

若元素的 display 为 none,则返回 0。

与 clientHeight 和 clientWidth 相比,这对属性使用频率更高,因为更多时候我们需要获取元素的完整宽高。

Element.offsetLeft,Element.offsetTop

返回当前元素左上角相对于 Element.offsetParent 节点的水平和垂直位移。

在此我们来了解下 Element.offsetParent:

Element.offsetParent 属性返回最靠近当前元素的、并且 CSS 的 position 属性不等于 static 的上层元素。

若该元素是不可见的(display属性为none),或者位置是固定的(position属性为fixed),则offsetParent属性返回null。

若某个元素的所有上层节点的position属性都是static,则Element.offsetParent属性指向元素自身。

摘自《阮一峰 JavaScript 教程》

相关方法

Element.getBoundingClientRect()

返回一个对象,提供当前元素的大小、位置等信息。

我常用它来获取元素的宽高和坐标。

该对象包含如下属性:

  • width
  • height
  • x 元素左上角相对于 视口 的横坐标
  • y
  • left
  • right
  • top
  • bottom

由于元素相对于视口(viewport)的位置会随页面滚动而变化,因此表示位置的四个属性值并非固定不变。若想得到绝对位置,可将 left 属性加上 window.scrollX,top 属性加上 window.scrollY。

摘自《阮一峰 JavaScript 教程》

MouseEvent 鼠标事件坐标详解

四 鼠标事件

MouseEvent 接口


let event = new MouseEvent('click', {
// ...
})

通过 addEventListener 添加的 click 事件所产生的事件对象也是 MouseEvent 实例。


let box = document.querySelector('.box')
box.addEventListener('click', (e) => {
console.log(e) // 事件对象
})

该事件对象,即 MouseEvent 实例,包含众多属性,此处进行简要分析。

MouseEvent.clientX 和 MouseEvent.clientY

只读属性

分别返回鼠标位置相对于 浏览器窗口 左上角的水平坐标和垂直坐标。(不受滚动距离的影响)

可以这样理解:

client 本意为客户端,在 web 中即指浏览器,因此 clientX 和 clientY 自然表示相对于浏览器的位置。

这两个属性还分别有一个别名 MouseEvent.x 和 MouseEvent.y。

MouseEvent.screenX,MouseEvent.screenY

只读属性

分别返回鼠标位置相对于 屏幕(显示器屏幕区域) 左上角的水平坐标和垂直坐标。

screen 意为屏幕,因此含义不言自明。

MouseEvent.offsetX,MouseEvent.offsetY

只读属性

分别返回鼠标位置相对于 目标节点(即当前元素) 左上角 padding 边缘 的水平距离和垂直距离。

offset 意为偏移,因此可理解为鼠标位置相对于目标元素内部左上角的偏移值,与目标元素本身及外部元素无关。

那 「padding 边缘」是什么意思呢?

我们通过图示说明:

前言与概述

上图中三个元素分别有红蓝绿三种边框来区分,红蓝边框宽度为 1px,绿边框为 30px。每个元素都有 padding 值。具体代码如下:


<!-- HTML -->
<body>
<div class="parent">
<div class="hello">Hello</div>
</div>
</body>
/* css */
body {
border: 1px solid red; margin: 0; padding: 20px;
}
.parent {
border: 1px solid blue; padding-top: 50px;
}
.hello {
width: 100px; height: 100px; padding: 100px; border: 30px solid green;
}

我们给 hello 元素添加一个 click 事件监听函数:


// js
let hello = document.querySelector('.hello')
hello.addEventListener('click', (e) => {
console.log(e)
console.log(e.offsetX)
console.log(e.offsetY)
})

分别点击 hello 元素的绿色边框和空白区域,会发现前者的值为负数,后者的值为整数,且都是相对空白区域的左上角开始计算的。

这就是我们一开始提到的 「鼠标位置相对于 目标节点(即当前元素) 左上角 padding 边缘 的水平距离和垂直距离」 这句话的含义。

MouseEvent.pageX,MouseEvent.pageY

只读属性

分别返回鼠标位置相对于文档左上角的距离。(包括滚动距离)

MouseEvent.movementX,MouseEvent.movementY

只读属性

返回当前位置与上一个 mousemove 事件之间的水平距离和垂直距离。

很明显这两个属性和 mousemove 事件肯定有着密切的关系,因此我们再了解一下 mousemove 事件:

当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次。

此处涉及「节流」概念,暂不深入探讨。

这两个属性颇具实用价值,虽然本人使用不多,但推测可用于判断鼠标的移动方向等场景。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章