JavaScript 的 Intersection Observer API 應用

sharkHead 程式技術 2個月前 • 0

最近在 iThome 看到一篇文章

GitHub揭露讓自家首頁飛快的開發秘訣

文章中有說明 Github 是如何在自家首頁中實作「當畫面滾動到某個位置時,就會出現對應的動畫特效」

小弟的前端技術還在努力中,但看到這一段還是讓我眼睛為之一亮
因為我好像在哪邊有用過 Intersection Observer API
在小弟的部落格中,文章頁面只要一往下滾,就會在右下角出現「返回頂部」的按鈕
方便用戶閱讀文章時,可以立即回到網頁的最上方

%E5%9C%96%E7%89%87%283%29.png
很多網站都會有類似的功能

在過去,如果要達到上述的功能,我們可以監聽 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


sharkHead

PHP 與 Python 菜雞工程師
最近在努力學習 TypeScript,希望可以突破慧根的限制