IntersectionObserver mulai muncul

IntersectionObservers memberi tahu Anda ketika elemen yang diamati masuk atau keluar dari area pandang browser.

Dukungan Browser

  • 51
  • 15
  • 55
  • 12.1

Sumber

Misalkan Anda ingin melacak kapan elemen di DOM Anda memasuki area pandang yang terlihat. Sebaiknya Anda melakukannya agar dapat lambat memuat gambar tepat pada waktunya atau karena Anda perlu mengetahui apakah pengguna benar-benar melihat banner iklan tertentu. Anda dapat melakukannya dengan menghubungkan peristiwa scroll atau dengan menggunakan timer berkala dan memanggil getBoundingClientRect() pada elemen tersebut.

Namun, pendekatan ini sangat lambat karena setiap panggilan ke getBoundingClientRect() memaksa browser menata ulang seluruh halaman dan akan menimbulkan cukup banyak jank di situs Anda. Masalah menjadi hampir mustahil ketika Anda tahu bahwa situs sedang dimuat di dalam iframe dan Anda ingin tahu kapan pengguna dapat melihat sebuah elemen. Model Asal Tunggal dan browser tidak akan mengizinkan Anda mengakses data apa pun dari halaman web yang berisi iframe. Ini merupakan masalah umum untuk iklan, misalnya, yang sering dimuat menggunakan iframe.

Membuat pengujian visibilitas ini lebih efisien adalah tujuan desain IntersectionObserver, dan fitur ini akan tersedia di semua browser modern. IntersectionObserver memberi tahu Anda saat elemen yang diamati memasuki atau keluar dari area pandang browser.

Visibilitas Iframe

Cara membuat IntersectionObserver

API-nya agak kecil, dan sebaiknya dijelaskan menggunakan contoh:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

Dengan menggunakan opsi default untuk IntersectionObserver, callback Anda akan dipanggil saat elemen muncul sebagian dan saat elemen sepenuhnya keluar dari area pandang.

Jika perlu mengamati beberapa elemen, Anda dapat mengamati beberapa elemen menggunakan instance IntersectionObserver yang sama dengan memanggil observe() beberapa kali.

Parameter entries diteruskan ke callback Anda yang merupakan array objek IntersectionObserverEntry. Setiap objek tersebut berisi data persimpangan yang diperbarui untuk salah satu elemen yang Anda amati.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds adalah hasil pemanggilan getBoundingClientRect() pada elemen root, yang merupakan area pandang secara default. boundingClientRect adalah hasil dari getBoundingClientRect() yang dipanggil pada elemen yang diamati. intersectionRect adalah titik potong dari dua persegi panjang ini dan secara efektif memberi tahu Anda bagian mana dari elemen yang diamati yang terlihat. intersectionRatio berkaitan erat, dan memberi tahu Anda seberapa banyak elemen tersebut terlihat. Dengan info ini, Anda kini dapat menerapkan fitur seperti pemuatan aset tepat waktu sebelum aset terlihat di layar. Efisien.

Rasio persimpangan.

IntersectionObserver mengirimkan datanya secara asinkron, dan kode callback Anda akan berjalan di thread utama. Selain itu, spesifikasi tersebut sebenarnya mengatakan bahwa implementasi IntersectionObserver harus menggunakan requestIdleCallback(). Artinya, panggilan ke callback yang Anda berikan memiliki prioritas rendah dan akan dilakukan oleh browser selama waktu tidak ada aktivitas. Ini adalah keputusan desain yang disengaja.

Scrolling div

Saya tidak suka men-scroll di dalam elemen, tetapi saya tidak bermaksud untuk menilai, begitu juga IntersectionObserver. Objek options menggunakan opsi root yang memungkinkan Anda menentukan alternatif area pandang sebagai root. Penting untuk diingat bahwa root harus merupakan ancestor dari semua elemen yang diamati.

Potong semuanya!

Tidak! Developer yang buruk! Itu bukan tindakan yang mempertimbangkan penggunaan siklus CPU pengguna Anda. Mari kita pikirkan tentang scroller tanpa batas sebagai contoh: Dalam skenario tersebut, sangat disarankan untuk menambahkan sentinl ke DOM dan mengamati (dan mendaur ulangnya!) tersebut. Anda harus menambahkan sentinel yang dekat dengan item terakhir dalam scrollinger tak terbatas. Saat sentinel itu terlihat, Anda bisa menggunakan callback untuk memuat data, membuat item berikutnya, melampirkannya ke DOM dan memosisikan ulang sentinel sebagaimana mestinya. Jika mendaur ulang sentinel dengan benar, Anda tidak perlu melakukan panggilan tambahan ke observe(). IntersectionObserver akan terus berfungsi.

Scroller tanpa batas

Tolong beri tahu lebih banyak

Seperti yang disebutkan sebelumnya, callback akan dipicu satu kali ketika elemen yang diamati muncul sebagian dan saat elemen yang diamati telah meninggalkan area pandang. Dengan cara ini, IntersectionObserver akan memberi Anda jawaban atas pertanyaan, "Apakah elemen X ada dalam tampilan?". Namun, dalam beberapa kasus penggunaan, hal itu mungkin tidak cukup.

Di sinilah opsi threshold akan digunakan. Hal ini memungkinkan Anda menentukan array nilai minimum intersectionRatio. Callback akan dipanggil setiap kali intersectionRatio melewati salah satu nilai ini. Nilai default untuk threshold adalah [0], yang menjelaskan perilaku default. Jika mengubah threshold menjadi [0, 0.25, 0.5, 0.75, 1], kami akan diberi tahu setiap kali seperempat elemen tambahan terlihat:

Animasi batas.

Ada opsi lain?

Untuk saat ini, hanya ada satu opsi tambahan untuk opsi yang tercantum di atas. rootMargin memungkinkan Anda menentukan margin untuk root, yang secara efektif memungkinkan Anda menambah atau mengecilkan area yang digunakan untuk persimpangan. Margin ini ditentukan menggunakan string bergaya CSS, yaitu á la "10px 20px 30px 40px", yang menentukan margin atas, kanan, bawah, dan kiri. Ringkasnya, struct opsi IntersectionObserver menawarkan opsi berikut:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

Keajaiban <iframe>

IntersectionObserver didesain khusus dengan mempertimbangkan layanan iklan dan widget jejaring sosial, yang sering menggunakan elemen <iframe> dan dapat memperoleh manfaat dengan mengetahui apakah elemen tersebut terlihat atau tidak. Jika <iframe> mengamati salah satu elemennya, men-scroll <iframe> maupun men-scroll jendela yang berisi <iframe> akan memicu callback pada waktu yang sesuai. Namun, untuk kasus yang terakhir, rootBounds akan disetel ke null untuk menghindari kebocoran data di seluruh origin.

Apa yang Bukan terkait dengan IntersectionObserver?

Perlu diingat bahwa IntersectionObserver sengaja tidak menjadikan piksel sempurna atau latensi rendah. Menggunakannya untuk mengimplementasikan upaya seperti animasi yang bergantung pada scroll pasti akan gagal, karena data tersebut akan—ketertinggalan—ketertinggalan pada saat Anda akan menggunakannya. Penjelasan berisi detail selengkapnya tentang kasus penggunaan asli untuk IntersectionObserver.

Berapa banyak pekerjaan yang dapat saya lakukan di callback?

Singkat 'n Bagus: Menghabiskan terlalu banyak waktu dalam callback akan membuat aplikasi Anda lambat—semua praktik umum berlaku.

Bergeraklah dan iris elemen-elemenmu

Dukungan browser untuk IntersectionObserver bagus, karena tersedia di semua browser modern. Jika perlu, polyfill dapat digunakan di browser lama dan tersedia di repositori WICG. Tentu saja, Anda tidak akan mendapatkan manfaat kinerja menggunakan polyfill yang akan diberikan oleh implementasi bawaan.

Anda dapat mulai menggunakan IntersectionObserver sekarang. Beri tahu kami saran Anda.