前端技術紀錄、everything I know

0%

【JS】 Intersection Observer(I) 基礎概念

監聽網頁元素是否進入用戶的 viewport 裡。在許多網頁裡,我們常常會遇到 JS 的功能。其中一個非常常見、常見到我們可能會以為這樣的功能應該不會太難做,就是當我們把網頁卷軸往下方滾動時,網頁會出現的變化,例如 navbar (網頁最上方的導覽列)出現顏色、透明度的變化,或是跳出「go to top」之類的按鈕。這樣的功能可以用 jQuery 很快速地做出來。大致上的概念是:監聽網頁卷軸滾動的狀態、持續地取得卷軸位置與該網頁頂部的距離、如果這個距離大於某些數值執行特定的函式(以導覽列為例,可能就是改變 class 名稱,以改變這個導覽列的樣式)。

一般我們可以使用 jQuery 或是、純 JS 監聽卷軸事件。

不過,因為「卷軸滾動」這樣的事件,不像是按鈕是非常態事件(正常狀態的使用下,沒有用戶會持續性地觸發按鈕),卷軸滾動是一個常態事件,不管做任何事情,基本上用戶都會滾動卷軸;也就是說,在用戶瀏覽網頁時,卷軸監聽的事件就會一直被觸發,直到關掉網頁為止。這樣看來,基於 JS 是單一執行序的程式語言,如果在瀏覽網頁、卷軸滾動時,網頁莫名地卡住一小段時間,或許就不會是太令人意外的事情了。

針對這個問題,有其他的解法。瀏覽器(除了 IE 11)有個 Web API:Intersection Observer,供我們觀測某個網頁元素是否進入 viewport。

Intersection Observer 是什麼?

在網頁的瀏覽中,我們把瀏覽器的視窗大小稱為 viewport,瀏覽器的可見範圍。一個網頁頁面通常會大於這個 viewport。透過卷軸,我們才可以瀏覽整個頁面。Intersection Observer 就是在偵測使用者瀏覽網頁時,特定的網頁元素是否進入這個瀏覽器的可見範圍內。這個網頁元素不管是從哪個方向進入瀏覽器的可計範圍,都會被偵測到。(圖例)

我們透過 intersection observer 的建構式,在網頁架起一個觀測器。然後,在執行的時候,再跟這個觀測器說,我要觀測哪個目標,這個觀測器就會在網頁上觀察這個目標。當目標進入視線時,這個觀測器就會建立一個陣列,例面紀錄了標的物的狀態。在這個標的物離開、甚至再次進入視線時,觀測器都會即時更新資訊。

另外,intersection observer 可以觀測單個或多個網頁元素。不過,以下我先就單個網頁元素做說明。

分隔線

使用方式

架一個偵測器

  • 需要的材料:
    1. 一個 function(方法和event listener 的 function 一樣)
    2. (選用)options,下一篇文章才會講到。
1
2
3
4
//observer function、偵測到某物件在可見範圍內,欲執行的動作
function observeHandler() {
// do something...
}
1
2
//抓取想要偵測的網頁元素, 意味著我們想要偵測這個網頁元素有沒有進入視窗的可見範圍
const element = // Select a DOM...
1
2
3
//  把上方兩個東西,代入 IntersectionObserver 的建構式
const observer = new IntersectionObserver(observeHandler); // 建立偵測器
observer.observe(element); // 執行偵測器、並且告訴這個偵測器要偵測什麼東西

附註

在使用 eventListener時,我們可以在 event handler 裡代入一個 e、查閱事件被驅動的資訊。intersection Observer 的 function 也可以做一樣的查閱。在代入 Intersection Observer 建構式中的function中,我們再代入一個參數(常用entries / entry ),就可以查看這個觀測器觀測到目標的狀態:

1
2
3
4
5
function observeHandler(entry) {
console.log(entry);
}

// 使用 entries 或是 entry 都可以

下圖是 console.log 的顯示結果,這兩個陣列是不同時間顯示出來的,可以看見 time 的時間不一樣。第一個陣列是目標離開可見範圍跳出來的紀錄、第二個陣列是觀測目標重新回到視線範圍的紀錄。我們可以從 isIntersecting 的 true / false 可以看出這個標的物是否在視線範圍內。

alt callback_entry

*

直接看範例:

說了這麼多,還是不比範例清晰: