最近在 iThome 看到一篇文章。
文章中有說明 Github 是如何在自家首頁中實作「當畫面滾動到某個位置時,就會出現對應的動畫特效」。
小弟的前端技術還在努力中,但看到這一段還是讓我眼睛為之一亮。
因為我好像在哪邊有用過 Intersection Observer API。
在小弟的部落格中,文章頁面只要一往下滾,就會在右下角出現「返回頂部」的按鈕。
方便用戶閱讀文章時,可以立即回到網頁的最上方。
在過去,如果要達到上述的功能,我們可以監聽 Scroll 事件。只要一監聽到滑鼠往下滾,就可以讓「返回頂部」的按鈕顯示。
但就如 iThome 那篇文章中 Github 所提到的。當用戶在滾動的時候,就會不停的觸發 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'));
這樣當 header 一消失在畫面上,返回頂部的按鈕就會出現在畫面上。
除了這種應用,Intersection Observer API 還能實現。
- 惰性加載:只有到對應的位置時才會開始載入圖片,節省頻寬。
- 無限滾動:滾動到底部時載入新的資料。