你想知道的HTML位置信息都在这里了

前言

在一次的波纹效果的实现中,由于用到了不少的HTML的位置信息,以前记得也就一两个,此次去翻阅MDN后发现,关于HTML的位置信息居然后不少参数。因而以为有必要将这些位置信息参数的含义作个总结,方便之后参考。html

一、Element

Element在是最通用的基类,一个DOM结构中全部的对象都是继承于它。包括后面介绍的HTMLElement也是继承于它。因此待会Element的属性HtmlElement也会拥有。chrome

1.一、clientHeight/clientWidth/clientLeft/clientTop

这四个参数标识的是元素的内部高度/宽度/左边border的宽度/上面border的宽度。其标识的含义以下图所示:数组

clientHeight是元素内部的高度,包含内边距也就是padding-top/padding-bottom,可是不包含水平滚动条、边框、和margin。浏览器

同理clientWidth也是如此。bash

clientLeft表示一个元素的左边框的宽度,有一些兼容性的问题能够详细参考Element.clientLeftide

clientTop也是如此。布局

四个参数的具体取值咱们如下面的demo来说解。测试

咱们使用超多的内容去填充div标签,而且设置了overflow属性让其出现水平滚动条或者垂直滚动条,可是这四个参数不为所动,验证了上面咱们刚才说的事实。ui

1.二、scrollHeight/scrollLeft/scrollLeftMax/scrollTop/scrollTopMax/scrollWidth

这6个参数和滚动相关,在页面的设计中不免会出现滚动条,想要知道用户滚到到哪一个位置就须要用到上面的某些参数来辅助你的判断。spa

scrollHeight标识元素的内容高度,注意和刚才的clientHeight加以区别。当元素不足以展现所有内容的时候使用overflow属性致使出现不可视的内容区域(也就是出现滚动条)的时候,这些不可视的内容也是包括在内的。在没有垂直滚动条的状况下,scrollHeight值与元素视图填充全部内容所须要的最小值clientHeight相同,它包含了元素的padding,但不包含margin。

scrollWidth也是相似。

scrollLeft能够读取或设置元素滚动条到元素左边的距离。

Tips

注意若是这个元素的内容排列方向(direction) 是rtl (right-to-left) ,那么滚动条会位于最右侧(内容开始处),而且scrollLeft值为0。此时,当你从右到左拖动滚动条时,scrollLeft会从0变为负数(这个特性在chrome浏览器中不存在)

scrollLeftMax返回一个Number表示一个元素横向滚动条可滚动的最大距离,兼容性比较差,属于新特性,谨慎使用。

scrollTop相似于scrollLeft。

scrollTopMax相似于scrollLeftMax。

咱们使用下面demo来讲明上面几个参数的用法。

在demo中咱们输出上面的四个参数(scrollLeftMax/scrollTopMax当前Chrome(v61)不支持)。 结果是:

scrollHeight: 222 scrollLeft: 0 scrollTop: 0 scrollWidth: 336

复制代码

当咱们把内容减小让其不要出现滚动条的时候:

能够看到:

scrollHeight: 102 scrollLeft: 0 scrollTop: 0 scrollWidth: 102 clientHeight: 102 clientWidth: 102 clientLeft: 2 clientTop: 2
复制代码

clientHeight === scrollHeight/clientWidth === scrollWidth

1.三、getBoundingClientRect()/getClientRects()

这两个方法也是用来获取元素的位置以及大小相关的信息。getClientRects返回的是个数组,数组中有不少个相似getBoundingClientRect返回的对象。getBoundingClientRect返回的永远是最外框框的那个矩形区域相关的坐标偏移对象;而getClientRects是多行文字区域的坐标偏移集合,在非IE浏览器下,只对inline的标签有反应。

通常getBoundingClientRect方法用的多一点。咱们能够很容易获取某个元素的偏移值。甚至高宽都能很轻松的计算出来。

1.3.一、getBoundingClientRect()

getBoundingClientRect返回一个DOMRect对象

DOMRect对象包含了一组用于描述边框的只读属性——left、top、right和bottom,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。

对象里面的元素以下表(引自DOMRect)

属性 类型 描述
bottom float Y 轴,相对于视口原点(viewport origin)矩形盒子的底部。只读。
height float 矩形盒子的高度(等同于 bottom 减 top)。只读。
left float X 轴,相对于视口原点(viewport origin)矩形盒子的左侧。只读。
right float X 轴,相对于视口原点(viewport origin)矩形盒子的右侧。只读。
top float Y 轴,相对于视口原点(viewport origin)矩形盒子的顶部。只读。
width float 矩形盒子的宽度(等同于 right 减 left)。只读。
x float X轴横坐标,矩形盒子左边相对于视口原点(viewport origin)的距离。只读。
y float Y轴纵坐标,矩形盒子顶部相对于视口原点(viewport origin)的距离。只读。

在这个demo中咱们看到对应的值:

(bottom,height,left,right,top,width,x,y): 114,106,9,115,8,106,9,8}

如何获得这些值呢?我绘制了这么一张图片,各个参数的取值由来罗列出来了:

须要注意的有如下几点:

  1. body元素浏览器默认给了8px
  2. body元素的margin和test1元素的margin-top发生了margin collapsing(外边距塌陷),因此获得的top值为8px,y值为8px
  3. right的值左边会包含元素的margin-left,可是不会包含margin-right,因此其值等于115,同理bottom也是。

1.3.二、getClientRects()

getClientRects返回一个ClientRect对象集合。提供以下的demo来解释这个方法:

能够在demo中能够看到第一个结果由于文字换行的个数获得集合数组的长度。每一行文字的位置信息咱们经过打印均可以看到,按照如今显示是两行,结果以下:

{"0":{"x":9,"y":5,"width":512.21875,"height":28,"top":5,"right":521.21875,"bottom":33,"left":9},"1":{"x":8,"y":27,"width":424.3125,"height":28,"top":27,"right":432.3125,"bottom":55,"left":8}}
复制代码

而div元素的不支持,因此始终获得的结果是一个,这个结果和获取getBoundingClientRect是同样的:

{"0":{"x":9,"y":75,"width":526,"height":50,"top":75,"right":535,"bottom":125,"left":9}}
复制代码

因此该方法主要用于判断行内元素是否换行,以及行内元素的每一行的位置偏移

二、HTMLElement

HTMLElement中介绍的是HTMLElement能够标识任何HTML元素。除了继承Element以外,它一样有一系列属于本身的位置参数定义。

2.一、offsetHeight/offsetLeft/offsetParent/offsetTop/offsetWidth

对块级元素来讲,offsetTopoffsetLeftoffsetWidthoffsetHeight描述了元素相对于offsetParent的边界框。

然而,对于可被截断到下一行的行内元素(如span),offsetTopoffsetLeft描述的是第一个边界框的位置(使用Element.getClientRects()来获取其宽度和高度),而offsetWidthoffsetHeight描述的是边界框的尺寸(使用 Element.getBoundingClientRect 来获取其位置)。

  1. HTMLElement.offsetParent是一个只读属性,返回一个指向最近的(closest,指包含层级上的最近)包含该元素的定位元素。若是没有定位的元素,则 offsetParent 为最近的table, table cell根元素(标准模式下为html;quirks模式下为body)。当元素的 style.display 设置为 "none" 时,offsetParent返回null。offsetParent 颇有用,由于offsetTopoffsetLeft都是相对于其内边距边界的。

  2. offsetHeight获取元素的像素高度,包括元素的边框、内边距和元素的水平滚动条(若是存在且渲染的话),不包含:before或:after等伪类元素的高度,且是一个整数。这个属性值会被四舍五入为整数值,若是你须要一个浮点数值,请用element.getBoundingClientRect()

  3. offsetLeft返回当前元素左上角相对于HTMLElement.offsetParent节点的左边界偏移的像素值。

  4. offsetWidth是一个只读属性,返回一个元素的布局宽度。一个典型的(译者注:各浏览器的offsetWidth可能有所不一样)offsetWidth是测量包含元素的边框(border)、水平线上的内边距(padding)、竖直方向滚动条(scrollbar)(若是存在的话)、以及CSS设置的宽度(width)的值。

  5. offsetTop为只读属性,它返回当前元素相对于其 offsetParent 元素的顶部的距离

其测试的demo以下:

三、事件中关于位置的信息

当咱们使用click事件或者touch事件的时候也一样会涉及到位置信息。Event包含了不少事件的定义,目前咱们只关注MouseEventTouchEvent

3.一、MouseEvent

鼠标点击事件,该事件接口可由这些事件触发:click/dbclick/mouseup/mousedown

MouseEvent继承自UIEvent,UIEvent继承自Event

该事件接口咱们关注三个参数:button/clientX/clientY/offsetX/offsetY/pageX/pageY/screenX/screenY。它们分别对应的信息是:

  1. button标识哪一种按钮被按了,通常有如下5种类型: 0: 标识主按钮触发的,通常指的是左边按钮或者是未初始化的状态 1: 辅助按钮触发的,通常指的是滚轮按钮或者是中间的按个按钮(若是存在的话) 2: 次级按钮触发的,通常指的是右边按钮 3: 第四个按钮,通常指的是浏览器的返回按钮 4: 第五个按钮,通常指的是浏览器的前进按钮

  2. clientX 是只读属性, 它提供事件发生时的应用客户端区域的水平坐标 (与页面坐标不一样)。例如,不论页面是否有水平滚动,当你点击客户端区域的左上角时,鼠标事件的 clientX 值都将为 0 。最初这个属性被定义为长整型(long integer),现在CSSOM视图模块将其从新定义为双精度浮点数(double float),clientY相似。

  3. movementX 是只读属性,它提供了当前事件和上一个mousemove事件之间鼠标在水平方向上的移动值。换句话说,这个值是这样计算的 : currentEvent.movementX = currentEvent.screenX - previousEvent.screenX.movementY相似。

  4. offsetX是鼠标点击的位置相对于目标节点内边位置的X坐标,offsetY相似。

  5. pageX 是一个由MouseEvent接口返回的相对于整个文档的x(水平)的坐标。这个属性考虑任何页面的水平方向上的滚动。 起初这个属性被定义为长整型。 CSSOM 视图模块将它从新定位为双浮点数类型。

  6. screenX是只读属性,标识鼠标点击的位置在全局坐标中横轴的偏移位置。screenY相似。

  7. x属性是clientX的简写,值等于clientX.

3.二、TouchEvent

触摸事件,经常使用于移动端设备。一次触摸能够产生一个Touch对象,TouchEvent中的touches表明了全部当前接触触摸平面的触点的 Touch对象。此次咱们着重关注touches这个属性。

touches是一个集合,集合里面的对象包含的属性大体和MouseEvent的是同样。可是也有些特有的属性:

  1. identifier: 此 Touch 对象的惟一标识符. 一次触摸动做(咱们值的是手指的触摸)在平面上移动的整个过程当中, 该标识符不变. 能够根据它来判断跟踪的是不是同一次触摸过程.

  2. radiusX标识可以包围用户和触摸平面的接触面的最小椭圆的水平轴(X轴)半径. 这个值的单位和 screenX 相同.radiusY相似

  3. rotationAngle: 它是这样一个角度值:由radiusX 和 radiusY 描述的正方向的椭圆,须要经过顺时针旋转这个角度值,才能最精确地覆盖住用户和触摸平面的接触面.

  4. force:手指挤压触摸平面的压力大小, 从0.0(没有压力)到1.0(最大压力)的浮点数.取决于移动设备的支持。

  5. target是触摸最开始触摸到的元素。哪怕在触点移动过程当中, 触点的位置已经离开了这个元素的有效交互区域, 或者这个元素已经被从文档中移除. 须要注意的是, 若是这个元素在触摸过程当中被移除, 这个事件仍然会指向它, 可是不会再冒泡这个事件到 window 或 document 对象. 所以, 若是有元素在触摸过程当中可能被移除, 最佳实践是将触摸事件的监听器绑定到这个元素自己, 防止元素被移除后, 没法再从它的上一级元素上侦测到从该元素冒泡的事件

两者事件的demo以下:

要查看touchEvent的位置信息须要把该demo在Chrome上调为移动端模式,点击一下框便可获得点击的位置信息。

四、最后的总结

属性 类型 说明
clientHeight/clientWidth float 元素内部的高度,只包含内边距也就是padding-top/padding-bottom,width相似
clientLeft/clientTop float 元素的左边框/上边框的宽度
scrollHeight/scrollWidth float 标识元素的内容高度内容宽度
scrollLeft/scrollTop float 能够读取或设置元素滚动条到元素左边/上边的距离
getBoundingClientRect().bottom/top float Y 轴,相对于视口原点(viewport origin)矩形盒子的底部/顶部。
getBoundingClientRect().height/width float 矩形盒子的高度/宽度(等同于 bottom 减 top/right 减 left)。
getBoundingClientRect().left/right float X 轴,相对于视口原点(viewport origin)矩形盒子的左/右侧。
getBoundingClientRect().x/y float X/Y轴横坐标,矩形盒子左边/顶部相对于视口原点(viewport origin)的距离。只读。
offsetHeight/offsetWidth int 元素的像素高度,包括元素的边框、内边距和元素的水平滚动条(若是存在且渲染的话),不包含:before或:after等伪类元素的高度
offsetLeft/offsetTop int 当前元素相对于其 offsetParent 元素的顶部的距离/左上角相对于HTMLElement.offsetParent节点的左边界偏移的像素值
clientX/clientY long 鼠标点击事件发生时的应用客户端区域的水平坐标 (与页面坐标不一样)
movementX/movementY float 当前事件和上一个mousemove事件之间鼠标在水平/垂直方向上的移动值
offsetX/offsetY float 鼠标点击的位置相对于目标节点内边位置的X/Y坐标
pageX/pageY float 一个由MouseEvent接口返回的相对于整个文档的x/y(水平/垂直)的坐标
screenX/screenY long 标识鼠标点击的位置在全局(屏幕)坐标中横轴/纵轴的偏移位置
radiusX/radiusY float 可以包围用户和触摸平面的接触面的最小椭圆的水平/纵轴轴(X/Y轴)半径

Tips:

  1. 带有client字眼的属性通常是衡量属性自身的尺寸(不包含不可见区域)
  2. 带有offset字眼的属性通常指的是元素相对于某个参照物的位置信息
  3. 带有page字眼的属性通常指的是元素相对于整个视图包括滚动未见的区域的位置信息
  4. 带有screen字眼的属性通常指的是元素相对于视图不包括不可见区域的位置信息

参考

  1. TouchEvent.touches
  2. Touch