JavaScript 的 Intersection Observer API 應用
最近在 iThome 看到一篇文章。
文章中有說明 Github 是如何在自家首頁中實作「當畫面滾動到某個位置時,就會出現對應的動畫特效」。
小弟的前端技術還在努力中,但看到這一段還是讓我眼睛為之一亮。
因為我好像在哪邊有用過 Intersection Observer API。
在小弟的部落格中,文章頁面只要一往下滾,就會在右下角出現「返回頂部」的按鈕。方便用戶閱讀文章時,可以立即回到網頁的最上方。
在過去,如果要達到上述的功能,我們可以監聽 Scroll 事件。只要一監聽到滑鼠往下滾,就可以讓「返回頂部」的按鈕顯示。
但就如 iThome 那篇文章中所提到的。當用戶在滾動的時候,就會不停的觸發 Scroll 事件,因此會耗費不少的資源。其實這樣的場景,我們可以考慮使用 Intersection Observer API 來處理。
Intersection Observer API 可以去觀察一個元素是否出現在瀏覽器窗口中。此 API 不需要事件處理器 (Event handler),而且由於是異步 (Asynchronous) 的,監聽元素是否在瀏覽器窗口中並非在主線程 (Main thread) 中執行,因此可以獲得不少的效能提升。
以部落格的移至頂部按鈕為例。首先在畫面上增加一個按鈕。
<button id="scroll-to-top-btn" title="Go to top" class="d-none">
返回頂部
</button>
新增一個 scroll-to-top-btn.js
去監聽按鈕。
// 取得返回頂部的按鈕
let scrollToTopButton = document.getElementById('scroll-to-top-btn');
scrollToTopButton.addEventListener('click', scrollToTop);
// 滾動到網頁的最上面
function scrollToTop() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
// 根據 header 是否出現在畫面上調整按鈕的樣式
let headerObserver = new IntersectionObserver(
function(entries) {
// 當 isIntersecting 為 true,代表此元素與瀏覽窗口是重疊的,意即元素有出現在畫面上
if (entries[0].isIntersecting === true) {
// 在 class 中加入 d-none
scrollToTopButton.classList.add('d-none');
} else {
// 移除 class 中的 d-none
scrollToTopButton.classList.remove('d-none');
}
},
{ threshold: [0] }
);
// 取得 header
// 開始監聽
headerObserver.observe(document.getElementById('header'));
// 當不再需要監聽器時,可以將其移除。節省記憶體
headerObserver.disconnect();
這樣當 header 一消失在畫面上,返回頂部的按鈕就會出現在畫面上。
除了這種應用,Intersection Observer API 還能實現。
- 惰性加載:只有到對應的位置時才會開始載入圖片,節省網路頻寬。
- 無限滾動:滾動到底部時載入新的資料。