Intersection observer檢測元素是否在視窗內

前端妹子發表於2019-01-03

前言

一直以來,檢測元素在瀏覽器視視窗內不是件容易的事,很多解決方案都不能很準確的判斷,計算量也有可能拖慢網站效能。 但是很多場景都需要用到:

  • 當頁面滾動時,懶載入圖片或其他內容。
  • 實現“可無限滾動”網站,也就是當使用者滾動網頁時直接載入更多內容,無需翻頁。
  • 為計算廣告收益,檢測其廣告元素的曝光情況。
  • 根據使用者是否已滾動到相應區域來靈活開始執行任務或動畫。

通常檢測是否在視窗內原理

監聽瀏覽器滾動事件scroll,對每個目標元素執行Element.getBoundingClientRect(),getBoundingClientRect方法返回元素的大小及其相對於視口的位置。 此方法可獲取整個網頁左上角定位 ,及距瀏覽器頂部的或左側的距離,然後用innerHeightinnerwidth等得到視窗大小,以此相減來判斷是否在視窗範圍內。

具體程式碼如下:codepen.io/raoenhui/pe…

還有其他檢測原理大多都是通過計算得到,但是下面我將要介紹由瀏覽器自帶方法檢測元素是否在視窗內。

新檢測原理Intersection observer

Intersection observer 允許你配置一個回撥函式,每當target進入瀏覽器視窗時,觸發回撥函式。

example1.gif

原始碼地址:codepen.io/raoenhui/pe…

用法

var options = {
    root: document.querySelector('#scrollArea'), 
    rootMargin: '0px', 
    threshold: 1.0
}
var callback = function(entries, observer) { 
    /* Content excerpted, show below */ 
};
var observer = new IntersectionObserver(callback, options);
複製程式碼

引數

options 配置項

  • root 目標元素。預設使用瀏覽器視口做為root
  • rootMargin root元素的外邊距。
  • threshold 閾值。可以是單一的number也可以是number陣列,一般取1。

callback 回撥函式

案例

example.gif

原始碼地址:codepen.io/raoenhui/pe…

target元素和root元素相交程度達到該值的時候IntersectionObserver註冊的回撥函式將會被執行。 如果你只是想要探測當target元素的在root元素中的可見性超過50%的時候,你可以指定該屬性值為0.5。如果你想要target元素在root元素的可見程度每多25%就執行一次回撥,那麼你可以指定一個陣列[0, 0.25, 0.5, 0.75, 1]。預設值是0(意味著只要有一個target畫素出現在root元素中,回撥函式將會被執行)。該值為1.0含義是當target完全出現在root元素中時候 回撥才會被執行。

外掛jquery_lazyload懶載入就是用到了此方法,

原始碼地址:github.com/tuupola/jqu…

 this.observer = new IntersectionObserver(function(entries) {
                entries.forEach(function (entry) {
                    if (entry.intersectionRatio > 0) {
                        self.observer.unobserve(entry.target);
                        let src = entry.target.getAttribute(self.settings.src);
                        let srcset = entry.target.getAttribute(self.settings.srcset);
                        if ("img" === entry.target.tagName.toLowerCase()) {
                            if (src) {
                                entry.target.src = src;
                            }
                            if (srcset) {
                                entry.target.srcset = srcset;
                            }
                        } else {
                            entry.target.style.backgroundImage = "url(" + src + ")";
                        }
                    }
                });
            }, observerConfig);
複製程式碼

相容性

相容性chrome基本支援,但是意外的是safari支援性不好,用到的小夥伴們要注意這點了,相容性具體看下圖:

image.png

其他連結

Happy coding .. :)

相關文章