js計算元素距離頂部的高度及元素是否在可視區判斷
前言:
在業務當中,咱們常常要計算元素的大小和元素在頁面的位置信息。好比說,在一個滾動區域內,我要知道元素A是在可視區內,仍是在隱藏內容區(滾動到外邊看不到了)。有時還要進一步知道,元素是所有都顯示在可視區,仍是有部分在可視區部分在隱藏內容區。有時還要進一步知道,在隱藏內容區的那一部分是佔多大的大小。so,來聊聊如何獲取元素的大小和位置信息。瀏覽器
計算元素距離頂部的高度:偏移量
在二維的世界裏,能夠想象成一個二維座標系。每個元素在座標系內都有兩個基本的屬性:大小和位置。框架
大小:
dom元素在頁面的大小有兩個屬性:offsetWidth 、offsetHeight,dom
offsetHeight:元素在垂直方向上的佔用空間大小,以像素計。包括元素的高度、(可見的)水平滾動條的高度、上邊框高度和下邊框高度。(個人理解:盒模型包括border內的高度總和)函數
offsetWidth: (同理) 佈局
位置:spa
offsetParent 是一個只讀屬性,返回一個指向最近的(closest,指包含層級上的最近)包含該元素的定位元素。若是沒有定位的元素,則 offsetParent 爲最近的 table, table cell 或根元素
offsetTop:元素相對於其 offsetParent 元素的頂部的距離code
offsetLeft:(同理)blog
元素大小和位置信息圖解element
原理:
計算元素距離頂部的高度:將元素的offsetTop與其offsetParent的相同屬性相加,如此循環直至根元素,就能夠獲得一個基本準確的值。封裝以下函數(開箱即用,函數返回值即爲元素距離頂部高度)get
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。