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的區別跟上面差很少。應該來講,這三個值在移動端不少時候都是相等的。

相關文章