获取 DOM 元素宽高、指针(光标/鼠标)坐标以及避坑指南

442 阅读3分钟

一、DOM 宽高

image.png

image.png

API 比较

注:content 宽度 不一定等于 CSS 声明的 width 值,依据 box-sizing 值有不同。

方法返回值描述读写能力
Element.style.widthstring(带设置单位),如果用户设置的是非法值,则返回空字符串。显式地通过style.width写入的string可读写
🌟 Element.offsetWidth整数型 number(小于 0.25 舍去,大于0.25进一),单位 px标准盒模型:width + padding + border
IE 盒模型:width
只读
Element.clientWidth整数型 number(小于 0.25 舍去,大于0.25进一),单位 px标准盒模型:width + padding
IE 盒模型:content
inline 元素值为 0
只读
Element.scrollWidth整数型 number(小于 0.25 舍去,大于0.25进一),单位 px元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
也包括 ::before 和 ::after这样的伪元素。
只读
window.getComputedStyle(element).width计算值或应用值,带 'px'string标准盒模型:width
IE 盒模型:width
只读(强制赋值报错)
Element.getBoundingClientRect.widthactual value 实际渲染值,浮点型 number,单位 px标准盒模型:width + padding + border
IE 盒模型:width
只读

DOM 元素 heigth 的获取也是相同的道理。

兼容性

所有方法放心使用,不必担心兼容性问题,其他如currentStyle等非标准属性就不做过多介绍。

clientHeightoffsetHeight兼容IE6以上

Element.getBoundingClientRect 兼容IE9以上浏览器

window.getComputedStyle 兼容IE9以上浏览器

经验

在实际开发中,因为clientWidthoffsetWidth获取的值会进行四舍五入,当数量多了就会累积误差,导致出现bug,在这个时候就可以使用getComputedStyle()或者更高精度的getBoundingClientRect()以获取实际渲染值。

二、指针坐标

指针坐标包含触控点坐标,鼠标坐标。可使用 MouseEvent、TouchEvent、PointerEvent 这三种事件获取。

image.jpg

API 比较

属性返回值描述
event.clientXnumber以浏览器窗口左边为原点,不论 Page 是否横向滚动。
event.xnumberevent.clientX的别名。
event.pageXnumber以 Page 左边为原点,考虑 Page 的滚动
event.screenXnumber以用户显示器左边为原点,如果水平方向多屏联动,也计算在内。
event.offsetXnumber事件对象与目标节点的内填充边(即以 padding 外边为起点)在 X 轴方向上的偏移量。
event.layerXnumber非标准,事件对象与目标节点的 border 边(以 border 外边为起点)在 X 轴方向上的偏移量。
event.movementX整数型 number它提供了当前事件和上一个 mousemove 事件之间鼠标在水平方向上的移动值。换句话说,这个值是这样计算的 : currentEvent.movementX = currentEvent.screenX - previousEvent.screenX
无论是指针还是鼠标事件,返回都是整数型 number,所以精度很差。

MouseEvent vs TouchEvent vs PointerEvent

比较:

  1. 返回值精度,MouseEvent 返回整数,TouchEventPointerEvent 返回浮点数。
  2. PointerEvent更通用但兼容性偏差 Safari 13 才支持,无论是何种触控方式,TouchEvent只适用于触摸操作,不适用于鼠标操作。

三、其他 API

offsetLeft/offsetTop

  1. HTMLElement.offsetLeft 是一个只读属性,返回当前元素左上角相对于  HTMLElement.offsetParent 节点的左边界偏移的像素值。
  2. HTMLElement.offsetLeft 是从 HTMLElement.offsetParentpadding 边界开始计算的(不包括offsetParentborder)。

clientLeft/clientTop

  1. 在标准盒子模型中,clientWidth = width + padding
  2. clientLeft 是当前元素的剩下的 border-left 的宽度;
  3. 不过在 IE 盒模型中,clientLeft 不变,依然等于 border-left 的宽度。

引用

  1. caniuse.com/?search=get…
  2. developer.mozilla.org/en-US/docs/…
  3. caniuse.com/?search=get…
  4. developer.mozilla.org/en-US/docs/…
  5. developer.mozilla.org/en-US/docs/…