DOM获取坐标的属性有哪些?

73 阅读2分钟
# DOM 获取坐标的属性详解

## 1. 元素相对于视口的坐标

### clientLeft/clientTop
- 表示元素左边框/上边框的宽度(包括滚动条宽度)
- 不包括外边距和内边距
- 只读属性

```javascript
const elem = document.getElementById('example');
console.log(elem.clientLeft, elem.clientTop);

clientWidth/clientHeight

  • 元素内容区+内边距的宽度/高度
  • 不包括边框、外边距和滚动条
  • 只读属性
console.log(elem.clientWidth, elem.clientHeight);

offsetLeft/offsetTop

  • 元素相对于最近定位祖先元素的左/上偏移
  • 如果祖先元素都没有定位,则相对于文档
  • 包括边框但不包括外边距
console.log(elem.offsetLeft, elem.offsetTop);

offsetWidth/offsetHeight

  • 元素整体尺寸,包括内容、内边距、边框和滚动条
  • 不包括外边距
  • 只读属性
console.log(elem.offsetWidth, elem.offsetHeight);

2. 元素相对于文档的坐标

getBoundingClientRect()

  • 返回一个DOMRect对象,包含元素相对于视口的位置和尺寸
  • 包括x/y(左上角坐标)、width/height、top/right/bottom/left
  • 会考虑CSS变换(transform)的影响
const rect = elem.getBoundingClientRect();
console.log(rect.left, rect.top);  // 相对于视口
console.log(rect.width, rect.height);

计算文档坐标

  • 通过结合getBoundingClientRect()和window.scrollX/scrollY
  • 可以获取元素相对于整个文档的绝对位置
const docX = rect.left + window.scrollX;
const docY = rect.top + window.scrollY;

3. 鼠标/触摸事件坐标

event.clientX/clientY

  • 鼠标指针相对于浏览器视口的坐标
  • 不随页面滚动变化

event.pageX/pageY

  • 鼠标指针相对于整个文档的坐标
  • 会考虑页面滚动位置

event.screenX/screenY

  • 鼠标指针相对于整个屏幕的坐标
elem.addEventListener('click', (e) => {
  console.log(e.clientX, e.clientY);  // 视口坐标
  console.log(e.pageX, e.pageY);      // 文档坐标
  console.log(e.screenX, e.screenY);  // 屏幕坐标
});

4. 滚动相关坐标

window.scrollX/scrollY

  • 文档当前水平/垂直滚动距离
  • 别名:window.pageXOffset/pageYOffset

element.scrollLeft/scrollTop

  • 元素内容水平/垂直滚动的像素数
  • 可读写属性
console.log(window.scrollX, window.scrollY);
console.log(elem.scrollLeft, elem.scrollTop);

5. 视口尺寸

window.innerWidth/innerHeight

  • 浏览器视口宽度/高度(包括滚动条)

document.documentElement.clientWidth/clientHeight

  • 视口宽度/高度(不包括滚动条)
console.log(window.innerWidth, window.innerHeight);
console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);

最佳实践建议

  1. 获取元素位置优先使用getBoundingClientRect()
  2. 考虑性能:避免在滚动/调整大小事件中频繁获取坐标
  3. 注意坐标系差异:视口坐标 vs 文档坐标
  4. 移动端开发要处理设备像素比(DPR)问题
  5. 复杂布局考虑使用IntersectionObserver替代滚动监听

兼容性注意事项

  1. IE8及以下不支持getBoundingClientRect()的width/height
  2. 旧浏览器可能需要polyfill
  3. 移动端touch事件坐标处理差异
  4. 某些CSS变换可能影响坐标计算结果

性能优化技巧

  1. 缓存DOMRect对象避免重复计算
  2. 使用requestAnimationFrame优化滚动相关计算
  3. 对于固定位置的元素,可以只计算一次坐标
  4. 考虑使用CSS sticky定位替代JS实现的粘性效果