Javascript 中的 Intersection Observer API 允許在頁面或容器中跟蹤元素的能見度。
問題
滾動頁面時,我們瀏覽其內容(平常是垂直的)。
螢幕右側有一個捲軸,指示頁面中的進度。
網頁中,如果想要跟蹤某些元素的能見度,可以監聽 scroll 事件來反應頁面的滾動:
window.addEventListener("scroll", () => {
const scrollPosition = window.scrollY;
// 根據位置執行操作,
// 根據能見度執行相關操作
});
這種方法可以用,但有什麼問題?
- 事件監聽函式會在滾動時重複執行,可能會過載主執行緒
- 為了判斷頁面上的元素是否可見,要先獲取其位置(例如使用
getBoundingClientRect()),再將其與頁面中的滾動位置比較,因此需要手動計算 - 如果想要判斷頁面可滾動容器中的元素是否可見,也需要手動計算,基於父元素的位置
Intersection Observer
Intersection Observer API 自然地解決這些問題。
從根元素開始,它會在交集區域中觀察元素。
當任何被觀察的元素進入或退出交集區域時,可以執行回呼函式。
根元素
建立 IntersectionObserver 實例時,可以傳遞選項。
選項中,可以指定根元素:root。如果未指定,則為整個頁面。它可以是任何可滾動的容器,其中想要監視某些元素的能見度。
const observer = new IntersectionObserver(
callback, // 回呼函式
{
// 根元素
root: document.getElementById("container"),
},
);
回呼函式
建立 IntersectionObserver 實例時,註冊回呼函式。
此函式會在兩種情況下執行:
- 實例建立時
- 被觀察的元素進入或退出交集區域時
它需要兩個參數:進入或退出交集區域的元素,以及 IntersectionObserver 的實例:
const observer = new IntersectionObserver(
(entries, observer) => {},
// 選項...
);
entries 中有一個元素陣列,每個元素都是 IntersectionObserverEntry 類型。可以循環遍歷它們並讀取有用資訊,例如:
isIntersecting, 最方便:元素是否在交集區域?intersectionRatio, 可有用:元素與根元素的交叉比例是多少?
觀察元素
觀察元素很簡單。建立 IntersectionObserver 實例後,呼叫 observe 函式並傳遞要觀察的元素:
observer.observe(element);
然後,當元素進入或退出交集區域時,回呼函式將被觸發。
交集區域
預設情況下,交集區域覆蓋整個根元素。當被觀察的元素接觸到這個區域時,它將被視為可見。
const observer = new IntersectionObserver(callback);
以上範例中,當元素進入區域時,它們被視為可見。因此看起來所有元素都是一直可見的。
rootMargin
可以通過傳遞選項來使交集區域更大或更小:rootMargin。
rootMargin 選項接受與 CSS margin 屬性相同的語法:top right bottom left。因此可以指定一個到四個數值,以像素、百分比或兩者為單位。
看看一個使用 rootMargin 到 -100px 的例子,它將交集區域減少一百像素:
const observer = new IntersectionObserver(callback, {
rootMargin: "-100px",
});
嘗試使用以下滑桿。要減少交集區域,因此會用負數值:
threshold
threshold 選項允許添加閾值,從而將元素視為可見。數值可用多種格式化:
0和1之間的數值等同於0%和100%之間的百分比。例如如果傳遞0.8,則元素在至少 80% 的內容可見時被視為可見。
使用 0.8 的例子:
const observer = new IntersectionObserver(callback, {
threshold: 0.8,
});
0和1之間的數值陣列,指示IntersectionObserver實例在目標的能見度百分比時執行回呼函式。
使用每次 10% 的呼叫,顯示元素的能見度百分比(intersectionRatio):
const observer = new IntersectionObserver(callback, {
threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
});
Output :處理表目錄
Intersection Observer API 使用的一個例子是處理表目錄。
閱讀文章時,當前部分被突出顯示。
就是 Astro Starlight 所做的:當段落標題進入交集區域時,相應的表目錄元素被突出顯示。
Astro Starlight 包含一個 web component。此組件包含 IntersectionObserver 實例的建立。
也會看到交集區域計算,使用 rootMargin 選項:獲取導航欄的高度,添加移動設備上表目錄的高度,得到交集區域的開始。53 像素後就是區域的結束。當標題穿越這個區域時,相應的表目錄元素將改變其外觀。
其實 Astro Starlight 定義了兩個 web components:一個用於 移動設備(顯示在螢幕頂部),另一個用於較大螢幕(顯示在右側)。