最近在 iThome 看到一篇文章
文章中有說明 Github 是如何在自家首頁中實作「當畫面滾動到某個位置時,就會出現對應的動畫特效」
小弟的前端技術還在努力中,但看到這一段還是讓我眼睛為之一亮
因為我好像在哪邊有用過 Intersection Observer API
在小弟的部落格中,文章頁面只要一往下滾,就會在右下角出現「返回頂部」的按鈕
方便用戶閱讀文章時,可以立即回到網頁的最上方
在過去,如果要達到上述的功能,我們可以監聽 Scroll 事件
只要一監聽到滑鼠往下滾,就可以讓「返回頂部」的按鈕顯示
但就如 iThome 那篇文章中 Github 所提到的
當用戶在滾動的時候,就會不停的觸發 Scroll 事件,因此會耗費大量的資源
為了解決這個問題,Intersection Observer API 便由此而生
Intersection Observer API 可以去觀察一個元素是否出現在瀏覽器窗口中
此 API 不需要事件處理器(Event handler),而且由於是異步(asynchronous)的,監聽元素是否在瀏覽器窗口中並非在主線程(main thread)中執行,因此可以獲得不少的效能提升
以部落格的移至頂部按鈕為例
首先在畫面上增加一個按鈕
<button class="d-none"
onclick="scrollToTop()" id="scroll-to-top-btn" title="Go to top">
返回頂部
</button>
新增一個 scroll-to-top-btn.js 去監聽按鈕
// 取得返回頂部的按鈕
let scrollToTopButton = document.getElementById('scroll-to-top-btn');
// 滾動到網頁的最上面
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 還能實現
參考資料
How to Know when an Element Gets Visible in the Screen During Scrolling
IntersectionObserver API 使用教程 - 阮一峰的網路日誌
Intersection Observer - MDN Web Docs