如何判斷元素是否在可視區域ViewPort

2021-09-13 01:15:52 字數 4022 閱讀 9554

個性簽名: 生如夏花,逝如冬雪;人生如此,何悔何怨。

前言: 經常需要計算元素的大小或者所在頁面的位置,offsetwidth,clientwidth,scrollwidth,scrolltop這幾個關鍵字的出現更是家常便飯,每次碰到都需要事先實驗一番。為了下次開發提高效率。在這裡一次性做個總結,以用來判斷元素是否在可視區域以及用原生js簡單實現懶載入。文末有個簡單的懶載入實現的demo,有需要的可以看一下。
目錄

工欲善其事,必先利其器。在判斷元素是否在可視區域實現簡單的原生懶載入前,我們先簡單回顧下以下幾個關鍵的概念。

ps: 如果你對這些概念已經比較熟悉了,可以直接跳到第五點檢視關鍵**示例。

偏移量(offset dimension),元素的可見大小由其高度、寬度決定,包括所有內邊距、滾動條和邊框大小(注意,不包括外邊距)。通過下列4個屬性可以取得元素的偏移量。

偏移量概念

公式offsetheight

元素在垂直方向上占用的空間大小,以畫素計。包括元素的高度、(可見的) 水平滾動條的高度、上邊框高度和下邊框高度。

offsetheght = content + padding + border + scrollx

offsetwidth

元素在水平方向上占用的空間大小,以畫素計。包括元素的寬度、(可見的)垂 直滾動條的寬度、左邊框寬度和右邊框寬度。

offsetwidth = content + padding + border + scrolly

offsetleft

元素的左外邊框至**包含元素的左內邊框之間的畫素距離。

offsettop

元素的上外邊框至包含元素的上內邊框之間的畫素距離。

其中,offsetleft 和 offsettop 屬性與包含元素有關,包含元素的引用儲存在 offsetparent 屬性中。**offsetparent 屬性不一定與 parentnode 的值相等。

如下圖顯示

注意:所有這些偏移量屬性都是唯讀的,而且每次訪問它們都需要重新計算。因此,應該盡量避免重複訪問這些屬性;如果需要重複使用其中某些屬性的值,可以將它們保 存在區域性變數中,以提高效能。

這也是上篇文章文字跑馬燈專案中(戳此跳轉),為什麼增加padding後,textwidth需要重新獲取的原因

小結 偏移量: 唯讀屬性;包括滾動條和邊框,不包括外邊距。

客戶區大小是唯讀的,每次訪問都要重新計算的。

客戶區大小

概念公式

clientwidth

clientwidth 屬性是元素內容區寬度加 上左右內邊距寬度;

clientwidth = content + padding

clientheight

元素內容區高度加上上下內邊距高度

clientheight = content + padding

最常用到這些屬性的情況,就是確定瀏覽器視口大小的時候(在 ie7 之前的版本中)。如下面的例子所示:

function getviewport();

} else ; }}

小結

客戶區大小: 唯讀屬性;不包括滾動條和邊框,不包括外邊距。

概念scrollheight

在沒有滾動條的情況下,元素內容的總高度。

scrollwidth

在沒有滾動條的情況下,元素內容的總寬度。

scrollleft

被隱藏在內容區域左側的畫素數。通過設定這個屬性可以改變元素的滾動位置。

scrolltop

被隱藏在內容區域上方的畫素數。通過設定這個屬性可以改變元素的滾動位置。

scrollwidth 和 scrollheight 主要用於確定元素內容的實際大小。

scrollleft 和 scrolltop屬性既可以確定元素當前滾動的狀態,也可以設定元素的滾動位 置。在元素尚未被滾動時,這兩個屬性的值都等於 0。如果元素被垂直滾動了,那麼 scrolltop 的值 會大於 0,且表示元素上方不可見內容的畫素高度。如果元素被水平滾動了,那麼 scrollleft 的值會 大於 0,且表示元素左側不可見內容的畫素寬度。這兩個屬性都是可以設定的,因此將元素的 scrollleft 和 scrolltop 設定為 0,就可以重置元素的滾動位置。比如:上篇文章文字跑馬燈專案中scrollleft的使用(戳此跳轉)

小結唯讀屬性,不包括滾動條、border。

getboundingclientrect

getboundingclientrect的相容性寫法:

對於不支援 getboundingclientrect()的瀏覽器,可以通過其他手段取得相同的資訊。一般來 說,right 和 left 的差值與 offsetwidth 的值相等,而 bottom 和 top 的差值與 offsetheight 相等。綜合上述,就可以建立出下面這個跨瀏覽器的函式:

function getelementleft(element)

return actualleft;

}function getelementtop(element)

return actualtop;

}function getboundingclientrect(element)

var rect = element.getboundingclientrect();

var offset = arguments.callee.offset;

return ;

} else }}

知道了元素的大小以及所位於的區域外,我們可以做些什麼呢?我們可以通過上面學到的知識點來檢測元素是否在可視區域,再說大一點,這也是懶載入的實現原理。

公式: el.offsettop - document.documentelement.scrolltop <= viewportheight

function isinviewportofone (el)
公式: el.getboundingclientreact().top <= viewportheight

其實, el.offsettop - document.documentelement.scrolltop = el.getboundingclientrect().top, 利用這點,我們可以用下面**代替方法一

function isinviewportoftwo (el)
公式: intersectionratio > 0 && intersectionratio <= 1

// 定義乙個交叉觀察器

const io = new intersectionobserver(ioes =>

el.onload = el.onerror = () => io.unobserve(el)

})})// 執行交叉觀察器

function isinviewportofthree (el)

在相容性方面,我們知道越原始的方法相容性是最好的,那麼第二種方法和第三種方法能否代替第三種方法呢?我們來看看。

從caniuse的資料來看,getboundingclientreact的適配情況很樂觀了。

所以,如果在移動端和桌面端都要做相容適配的話,方法二完全可以代替方法一進行適配了。如果僅僅是桌面端適配(比如運營後台),我們或許可以嘗試下新的intersectionobserver方法,畢竟intersectionobserver裡面還有更多豐富的功能等著我們去體驗呢。

有時,我們希望某些靜態資源(比如),只有使用者向下滾動,它們進入視口時才載入,這樣可以節省頻寬,提高網頁效能。這就叫做"惰性載入",也稱為懶載入。

惰性載入預覽demo(放入你的本地即可通過更換不同方法實現懶載入)

------------------------------ 華麗的分割線 ---------------------------

關於我

參考

如何判斷乙個元素是否在可視區域內

以使用 jquery 實現為參考 目標元素 card let card card 當頁面滾動時,元素隨頁面滾動,該元素距離頂部的距離 let cardoffsettop card offset top 獲取 card 的高度 card 包含外邊距 let cardouterheight card o...

元素進入可視區域執行

doctype html html lang en head meta charset utf 8 title title title style show show keyframes loading to style head body p id show p script newclassna...

js 判斷進入可視區域

1.使用場景 2.實現 監聽網頁滾動事件 window scroll function 拓展 獲取指定元素距離網頁左上角 0,0 的縱向偏移距離 該值會隨著滾動條的變化而變化 scrolltop變大,該值變小 scrolltop變小,該值變大 document.getelementbyid id g...