前言
前陣子在前端群組,看到有人提到這個 API,以前完全沒使用過也沒聽過,看了下大家討論及爬了下文,發現使用場景挺多的,比如「lazy loading、無限滾動、Sticky Header」等等,於是決定來做個筆記及動手做些實作。
認識 Intersection Observer
中文直接翻譯叫做「路口觀察者」(?,我也不大曉得大家如何稱呼他,如果有好的繁體翻譯名稱麻煩再跟我說。
是一個用來觀察、監控某個元素是否進入或是離開可視區域的 Javascript API,不需要使用 scroll 事件,即可實現 scroll 事件延伸出來的相關功能。
Intersection Observer 與 scroll 的差異
以前在上面提到的 scroll 功能時,都是使用 scroll 來做監聽,那為什麼要使用 Intersection Observer 這個新的API 來做這些事呢?下表有簡略介紹兩者差異。
兩者差異 |
scroll | Intersection Observer |
---|---|---|
使用滾輪時 | 有機會不斷觸發 scroll 事件 | 只在特定元素進入或離開可視區域時觸發事件 |
如何使用 | 需做各種計算,EX:元素位置、滾輪的位置等等,產生額外的效能 | 只需觀察特定元素,在進入或離開時做處理 |
開始使用
首先,這個 API 是一個建構函式,所以需要將它 new 出來
const io = new IntersectionObserver(callback, options);
再來將 io 創建好後,可看見裡面有兩個參數,callback 及 options,這兩個參數分別為:
callback:當觀察的元素進入到視窗範圍內就會在此執行 callback。
options:這裡面放的是一個物件,可以用來放入三個屬性,分別為 root、rootMargin、threshold。
callback用法:
const callback = (entries, io) => {
// 觸發 callback 時想做的處理放這裡面,有兩個參數
// entries 為觀察的目標元素,是一個陣列,所以可以用迴圈的方式使用它
// io 為 IntersectionObserver 實例本身
entries.forEach((entry) => {
console.log(entry)
// console.log(entry)會發現裡面有許多屬性,下方會解釋各個屬性的用途
})
}
entry 中的各個屬性:
boundingClientRect:目標元素的方形區域資訊,與 JS 的 getBoundingClientRect 這個API功能差不多。
intersectionRatio:當目標元素進入到觀察區域範圍的比例,比如目標元素在觀察範圍內 10%左右,會顯示0.11111111%,當目標元素完整的在觀察區域範圍內時的值為 1,完整離開的值為 0。
intersectionRect:表示目標元素區塊與觀察區域區塊相交的資訊。
isIntersecting:是一個布林值,表示目標元素區塊與關察區域區塊是否相交。
rootBounds:root的 getBoundingClientRect 資訊。
target:觀察的目標元素。
time:callback 觸發的時間。
options用法:
const options = {
root: null, // 不設定時,預設為 null,也就是整個頁面都會被觀察,或著可以
// 或是可以觀察一個 container 區塊,EX:root: document.querySelector('.container')
rootMargin: '0px 0px 0px 0px', // 這個和 css的 margin 類似,可以用來增加或縮小觀察的範圍,
// 可設定正數及負數以及百分比
threshold: 1 // 此為滾輪滾至觀察到的目標元素的比例,可以設定 0~1,
// 比方說設置為 1,目標元素需要完整的在觀察區域範圍內
// 才會觸發 callback,若是為 0.1,則是只要目標元素有 10%在視窗範圍內就會觸發 callback
// 也可以寫成陣列的型式 [0, 0.25, 0.5, 0.75, 1]
// 表示每過觀察區塊的 25% 就觸發一次 callback
}
了解如何創建觀察器後,就能開始使用它啦!
observer 這個建構函式有三個方法,分別為 observe、unobserve、disconnect。
observe:此方法用來指定觀察目標元素。
unobserve:此方法用來停止觀察目標元素。
disconnect:使方法用來停止"所有"觀察。
使用範例如下:
const target = document.querySelector('.target')
observer.observe(target)
observer.unobserve(target)
observer.disconnect()
需注意,觀察的目標元素需在 root 內,比方說 root 有指定一個 container 容器,target 則要放在 container中。
以上,了解了如何使用後,就可以開始做些實作啦!