C1:DOM 元素的尺寸和位置

DOM元素的尺寸和位置

DOM 元素的尺寸

DOM.offsetWidth/offsetHeight:

包括内容区宽/高,padding,border,不包括margin.
若是元素的box-sizeing是border-box,那么此时设置的style.width/style.height就是该元素的offsetWidth/offsetHeight.也就是等于内容区的宽/高 + padding + border + 滚动条。html

DOM.clientWidth/clientHeight:

包括内容区宽/高padding,不包括border 和margin.
在box-sizing:border-box的状况下,等于style.width/height - border的宽度。
这里还有另一种换算方法:clientWidth/clientHeight = offsetWidth/height - border - 滚动条的宽/高浏览器

DOM.scrollWidth/scrollHeight:

包括内容区的宽/高padding,以及子元素超出的宽/高,不包括border.
就是clientWidth / clientHeight 加上其子元素超出的宽/高。
box-sizing:border-box的状况也是同样。
值得注意的是:这里 DOM的子元素超出部分 的计算随着DOM的overflow的取值不一样而略有不一样。
以下:绿色盒子宽高100px,padding:20px;box-sizing:content-box里面有一个高度为200px的红色盒子函数

clipboard.png

当绿色盒子的overflow为默认值的时候,绿色盒子的scrollHeight = 上边距 20px + 红色盒子的高度 = 220px
当绿色盒子的overflow属性为auto,scroll,hidden中的任意一个的时候,其scrollHeight = 上边距 + 下边距 + 红色盒子的高度 = 20 + 20 +200 = 240pxspa

DOM.style.width/style.height:

返回style属性中的width和height。这两个值根据box-sizing 的取值不一样所表示的范围也不一样。
使用DOM.style.width/height 这种方式只能取到行内样式,而取不到CSS样式中的属性值。更多时候,咱们可能须要的是这个方法:
window.getComputedStyle(DOM) 返回一个DOM元素计算后的style对象。
当box-sizing:content-box的时候,style.width/height = offsetWidth/height - 滚动条的宽/高 - border - 内边距。
当box-sizing :border-box的时候,style.width/height 就等于offsetWidth / offsetHeight3d



<html> 和<body> 的尺寸

<html> 的clientHeight 和clientWidth 永远等于viewport - 滚动条的宽度/高度(移动端除外),不论box-sizing的取值是什么。
<body> 的尺寸计算方式和普通的DOM元素是同样的。指针

Element.getBoundingClientRect()

返回一个DOMRect对象,包含left ,top,width,height 四个属性的边框集合

其中的left ,top 是相对于视口左上角而言的。若是元素滚动了,left,top值也是变化的。width/height就是元素的盒子模型(border + padding + content + 滚动条)的计算宽度和高度。对于html和body一样适用。code

DOM元素的位置

使用element.getBoundingClientRect()咱们能够获得元素相对于viewport的位置。orm

还有一种方法能够获得元素相对于最近定位的祖先元素的位置,就是使用element.offsetTop和element.offsetLeft 属性。htm

这里有另一个能够获得元素相对于根元素(一般状况下根元素指的是视口),根据element.offsetParent 一直向上查找,直到element.offsetParent == null。html,body的offsetParent都为null.对象

let current = element.offsetParent
let top = element.offsetTop
while(current){
    top = current.offsetTop 
    current = current.offsetParent
}

值得注意的是,element.offsetTop/offsetLeft的计算的是element元素外边框到包含它的元素的内边框之间的距离。因此严格上来讲,应该还要依据状况加上边框的宽度的。可是边框通常不会很大,最多1px 2px,因此能够忽略。



click 事件中鼠标指针的位置

在PC,移动端的click事件中mouseEvent 都会包含如下信息

e.clientX/e.clientY:

返回鼠标指针相对与浏览器窗口客户区的坐标。

e.pageX/e.pageY:

返回鼠标指针相对于整个文档的坐标。浏览器没有滚动条的时候,这个值和e.clientX/e.clientY 是同样的。可是有滚动条的时候,这个值就会比e.clientX/e.clientY大。

e.screenX/e.screenY

返回鼠标指针相对于整个屏幕的坐标。哪怕此时你的浏览器被你缩小了移动到了角落,它的计算基准都是物理屏幕的左上角。

e.offsetX/e.offsetY

返回鼠标指针相对于e.target的坐标,这一点要区别于e.currentTarget。因为事件的冒泡,因此当底层的元素点击事件冒泡到顶层的时候,在顶层事件处理函数中的event 对象中的offsetX/offsetY 仍是相对于最初触发的底层元素。
若是祖先元素有translate,scale貌似这个值获取不对。。。
换一种方法获取吧,e.clientX,e.clientY配合element.getBoundingClientRect()

function getOffset(e){
    let target = e.currentTarget
    let rect = target.getBoundingClientRect()
    return {
        x: e.clientX - rect.left,
        y: e.clientY - rect.top
    }
}

这样子无论其祖先元素有没有设置transform,均可以在点击的时候得到鼠标指针位置相对于e.currentTarget的相对坐标。

移动端touch事件中一些关于位置的有用信息

移动端的touch 事件咱们也能获得许多相似的信息,这些信息存在e.touches 的touch对象中。

touch.screenX/touch.screenY:

返回相对于屏幕边沿的坐标。

touch.clientX/touch.clientY:

返回相对于viewport边沿的坐标。

touch.pageX/touch.pageY:

返回相对于文档边沿的坐标。和clientX/clientY的区别跟上面差很少。应该来讲,这三个值在移动端不少时候都是相等的。

相关文章