Saya baru-baru ini harus membuat Scrollspy untuk portofolio web pribadi saya. Saya ingin menggunakan Intersection Observer karena sekarang didukung secara luas. Sayangnya, ini tidak terlalu sederhana dan tidak banyak informasi di internet tentang cara membuatnya berfungsi. Jadi, saya memutuskan untuk menulis artikel kecil untuk membantu orang lain yang mencari hal yang sama.

Scrollspy adalah mekanisme navigasi yang digunakan oleh Bootstrap. Sesuai dokumen,

Scrollspy

Perbarui navigasi atau daftar komponen grup secara otomatis berdasarkan posisi gulir untuk menunjukkan tautan mana yang sedang aktif di area pandang.

Pada dasarnya, ini adalah bagian dari JavaScript yang memungkinkan header dan daftar Anda mengetahui elemen mana yang saat ini ada di layar. Ini biasanya digunakan untuk menyorot bagian aktif di bilah navigasi.

Pengamat Persimpangan

Sebelumnya, efeknya dicapai dengan menggunakan pendengar peristiwa gulir yang akan memeriksa semua bagian satu per satu pada setiap gulir dan kemudian memperbarui bagian yang saat ini ada di area pandang agar aktif. Untungnya, kami memiliki IntersectionObserver API baru yang membuat tugas menjadi lebih sederhana dan efisien.

IntersectionObserver digunakan untuk memantau bagian tertentu dari area pandang untuk memeriksa kapan node DOM tertentu berpotongan dengan wilayah tersebut. Setiap kali node memasuki atau meninggalkan wilayah tersebut, panggilan balik dijalankan.

Jika Anda belum tahu tentang IntersectionObserver API, lihat artikel bagus ini. Manfaat utama dari pengamat persimpangan adalah tidak seperti pemroses peristiwa gulir, pengamat ini bersifat asinkron.

Parameter dan opsi

IntersectionObserver API mengambil opsi berikut:

  1. Akar persimpangan: Wilayah yang akan dipantau persimpangannya dengan node tertentu. Defaultnya adalah viewport tetapi juga dapat diatur ke node DOM.
  2. Margin root: Secara default, seluruh root dipantau. Tapi kita bisa menentukan margin di sekitar root untuk memantau wilayah yang lebih besar (atau lebih kecil jika marginnya negatif) daripada root.
  3. Ambang Batas: Nilai antara 0 dan 1 yang menentukan berapa banyak bagian elemen target yang harus berada di akar persimpangan untuk memicu fungsi panggilan balik. 0 berarti segera setelah satu piksel memasuki wilayah tersebut atau segera setelah seluruh node meninggalkan wilayah tersebut. 1 berarti seluruh node harus berada di wilayah tersebut. Beberapa nilai dapat diberikan dalam bentuk array.
  4. Callback: Fungsi yang dipanggil setiap kali terjadi persimpangan.

Langkah pertama adalah membuat pengamat menggunakan opsi di atas. Kemudian elemen target didaftarkan pada pengamat persimpangan. Jika salah satu elemen berpotongan dengan wilayah tertentu dalam nilai ambang batas, panggilan balik akan dipanggil. Sesuai MDN, Sintaks untuk panggilan balik adalah:

let callback = (entries, observer) => {
  entries.forEach(entry => {
    // Each entry describes an intersection change for one observed
    // target element:
    //   entry.boundingClientRect
    //   entry.intersectionRatio
    //   entry.intersectionRect
    //   entry.isIntersecting
    //   entry.rootBounds
    //   entry.target
    //   entry.time
  });
};

entries parameter berisi entri untuk semua node yang diamati. Untuk mengetahui entri mana yang berpotongan dengan root, gunakan properti entry.isIntersecting.

Tekniknya

Katakanlah kita memiliki halaman dengan beberapa bagian dan kita perlu mencari bagian mana yang saat ini menjadi fokus utama. Di sini kami melakukan hal berikut:

  1. Pertahankan threshold hingga 0 (nilai default). Artinya setiap kali piksel pertama dari bagian mana pun memasuki area pandang atau piksel terakhir dari bagian mana pun meninggalkan root, callback akan dieksekusi.
  2. Akar persimpangan adalah seluruh area pandang secara default. Kami ingin persimpangan diamati pada garis horizontal. Kita dapat melakukannya dengan menambahkan margin pada akar dan mengurangi area pengamatan menjadi garis horizontal. Untuk menyetelnya tepat di tengah layar, setel rootMargin ke -50% 0px
  3. Dapatkan daftar semua bagian di halaman dan hubungkan ke pengamat persimpangan.
  4. Setiap kali terjadi persimpangan, cari tahu elemen mana yang menyebabkan persimpangan tersebut. Untuk melakukan itu, gunakan properti entry.isIntersecting.

Kode cukup mudah:

window.onload = () => {
  const sections = document.getElementsByTagName("section");
  const label = document.getElementById("section-name");
  
  const observer = new IntersectionObserver((entries) => {
    for(const entry of entries)
      if(entry.isIntersecting)
        label.innerHTML = entry.target.innerText;
    },{
    rootMargin: "-50% 0px"
  });
  for (let i = 0; i < sections.length; i++)
   observer.observe(sections[i]);
};

Anda dapat melihatnya beraksi di sini: http://intersection-scrollspy.surge.sh/