前言: 在業務當中,我們經常要計算元素的大小和元素在頁面的位置信息。比如說,在一個滾動區域內,我要知道元素A是在可視區內,還是在隱藏內容區(滾動到外邊看不到了)。有時還要進一步知道,元素是全部都顯示在可視區,還是有部分在可視區部分在隱藏內容區。有時還要進一步知道,在隱藏內容區的那一部分是占多大的大小 ...
前言:
在業務當中,我們經常要計算元素的大小和元素在頁面的位置信息。比如說,在一個滾動區域內,我要知道元素A是在可視區內,還是在隱藏內容區(滾動到外邊看不到了)。有時還要進一步知道,元素是全部都顯示在可視區,還是有部分在可視區部分在隱藏內容區。有時還要進一步知道,在隱藏內容區的那一部分是占多大的大小。so,來聊聊如何獲取元素的大小和位置信息。
計算元素距離頂部的高度:偏移量
在二維的世界里,可以想象成一個二維坐標系。每一個元素在坐標系內都有兩個基本的屬性:大小和位置。
大小:
dom元素在頁面的大小有兩個屬性:offsetWidth 、offsetHeight,
offsetHeight:元素在垂直方向上的占用空間大小,以像素計。包括元素的高度、(可見的)水平滾動條的高度、上邊框高度和下邊框高度。(我的理解:盒模型包括border內的高度總和,不包括margin)
offsetWidth: (同理)
位置:
offsetTop:元素的上外邊框至包含元素的上內邊框之間的像素距離。
offsetLeft:(同理)
元素大小和位置信息圖解
原理:
計算元素距離頂部的高度:將元素的offsetTop與其offsetParent的相同屬性相加,如此迴圈直至根元素,就可以得到一個基本準確的值。封裝如下函數(開箱即用,函數返回值即為元素距離頂部高度)
function getElementTop (el) {
var actualTop = el.offsetTop
var current = el.offsetParent
while (current !== null) {
actualTop += current.offsetTop
current = current.offsetParent
}
return actuanlTop
}
分析一下代碼:
計算元素距離頂部的高度:(同理可得)
元素是否在可視區判斷:結合scrollTop
假如這樣的業務場景:有一個wrap滾動容器,wrap的內容區content的高度超過wrap的高度,則出現縱向滾動條。隨意拖動滾動條到某個位置,要判斷content裡面的子元素input輸入框是否在可視區內,若不在可視區內,自動拖動滾動條,使其進入可視區。這樣的業務場景其實經常有遇到。
原理:
首先,根據以上getElementTop(domInput)函數,得到元素input距離頂部的高度elementTop。再結合滾動容器domWrap的scrollTop屬性得到滾動條高度scrollTop(被隱藏在內容區域上方的像素數),進行比較,即可判斷
scrollTop > elementTop: 滾動條高度大於元素離頂部高度,說明元素進入了隱藏內容區,進入的量為 scrollTop - elementTop
scrollTop < elementTop:滾動條高度小於元素的離頂部高度,說明元素還沒進入上方的隱藏內容區,如要保證元素在可視區內,則必須同時滿足條件,元素不在下方的隱藏內容區: elementTop - scrollTop < document.documentElemnt.clientHeight
結論:
所以,元素在可視區的初步判斷條件為:scrollTop < elementTop && elementTop - scrollTop < document.documentElemnt.clientHeight
以上判斷還不太嚴謹,如果wrap還同時存在橫向滾動條,還得再判斷是否元素在橫向的可視區內,如果要判斷元素是否完全在可視區,還得加上自身的高度值,即為:scrollTop < elementTop && elementTop + input.offsetHeight - scrollTop < document.documentElemnt.clientHeight。
通過設置scrollTop屬性的值domWrap.scrollTop = elementTop 可以讓滾動條自動滾動,且input元素剛好在可視區的上方。
ps:書上是這麼說的,對於簡單的CSS佈局的頁面,getElementTop函數可以得到非常精確的結果。對於使用表格和內嵌框架佈局的頁面,由於不同瀏覽器實現這些元素的方式不同,因此得到的結果就不太精確。在我的業務中,我沒有用到表格和內嵌框架的佈局,計算結果確實是精確的,可放心使用。如果使用表格和內嵌框架佈局的頁面,Keeping a eye on it。
參考: Javascript高級程式設計(第三版)