IntersectionObservers memberi tahu Anda saat elemen yang diamati memasuki atau keluar dari area pandang browser.
Misalkan Anda ingin melacak kapan elemen dalam DOM memasuki area pandang yang terlihat. Anda mungkin ingin melakukan ini sehingga Anda dapat memuat gambar secara lambat tepat pada waktunya atau karena Anda perlu tahu 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 jank yang cukup besar ke situs Anda. Masalah nyaris tidak mungkin terjadi jika Anda mengetahui bahwa situs dimuat di dalam iframe dan Anda ingin mengetahui kapan pengguna dapat melihat elemen. Model Asal Tunggal dan browser tidak akan mengizinkan Anda mengakses data apa pun dari halaman web yang berisi iframe. Ini adalah masalah umum untuk iklan, misalnya, yang sering dimuat menggunakan iframe.
Membuat pengujian visibilitas ini lebih efisien adalah hal yang dirancang untuk IntersectionObserver
, dan tersedia di semua browser modern. IntersectionObserver
memberi tahu Anda saat elemen yang diamati memasuki atau keluar dari area tampilan browser.
Cara membuat IntersectionObserver
API-nya cukup 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 akan dipanggil saat elemen muncul sebagian di tampilan dan saat elemen benar-benar keluar dari area pandang.
Jika Anda 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 dari memanggil getBoundingClientRect()
pada elemen root, yang merupakan area tampilan secara default. boundingClientRect
adalah hasil getBoundingClientRect()
yang dipanggil pada elemen yang diamati. intersectionRect
adalah perpotongan dari dua persegi panjang ini dan secara efektif memberi tahu Anda bagian mana dari elemen yang diamati yang terlihat. intersectionRatio
terkait erat, dan memberi tahu Anda seberapa banyak elemen yang terlihat. Dengan informasi ini, Anda sekarang dapat menerapkan fitur seperti pemuatan aset tepat waktu sebelum terlihat di layar. Efisien.
IntersectionObserver
mengirim datanya secara asinkron, dan kode callback Anda akan berjalan di thread utama. Selain itu, spesifikasi tersebut sebenarnya menyatakan bahwa implementasi IntersectionObserver
harus menggunakan requestIdleCallback()
. Hal ini berarti panggilan ke callback yang Anda berikan memiliki prioritas rendah dan akan dilakukan oleh browser selama waktu tidak ada aktivitas. Ini adalah keputusan desain sadar.
Scrolling div
Saya tidak suka men-scroll di dalam elemen, tetapi saya tidak ada di sini untuk menilai, begitu juga IntersectionObserver
. Objek options
menggunakan opsi root
yang memungkinkan Anda menentukan alternatif area tampilan sebagai root. Penting untuk diingat bahwa root
harus menjadi ancestor dari semua elemen yang diamati.
Potong-potong semuanya!
Tidak! Pengembang yang buruk! Hal tersebut tidak mempertimbangkan penggunaan siklus CPU pengguna Anda. Mari kita pikirkan tentang scrollinger tanpa batas sebagai contoh: Dalam skenario tersebut, tentu saja disarankan untuk menambahkan sentinel ke DOM dan mengamati (dan mendaur ulang) kalimat tersebut. Anda harus menambahkan sentinel di dekat item terakhir dalam Infinite scroller. Saat sentinel tersebut muncul, Anda bisa menggunakan callback untuk memuat data, membuat item berikutnya, melampirkannya ke DOM, dan mengubah posisi sentinel. Jika Anda mendaur ulang sentinel dengan benar, panggilan tambahan ke observe()
tidak diperlukan. IntersectionObserver
tetap berfungsi.
Info terbaru lainnya
Seperti yang disebutkan sebelumnya, callback akan dipicu satu kali saat elemen yang diamati muncul sebagian di tampilan dan di lain waktu saat elemen yang diamati telah meninggalkan area pandang. Dengan cara ini IntersectionObserver
memberi Anda jawaban atas pertanyaan, "Apakah elemen X terlihat?". Namun, dalam beberapa kasus penggunaan, hal tersebut mungkin tidak cukup.
Di sinilah opsi threshold
berguna. Hal ini memungkinkan Anda menentukan array nilai minimum intersectionRatio
. Callback Anda 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 mendapatkan notifikasi setiap kali seperempat tambahan elemen terlihat:
Ada opsi lain?
Untuk sekarang, hanya ada satu opsi tambahan selain yang tercantum di atas. rootMargin
memungkinkan Anda menentukan margin untuk root, yang secara efektif memungkinkan Anda memperbesar atau mengecilkan area yang digunakan untuk persimpangan. Margin ini ditetapkan menggunakan string gaya CSS, á la "10px 20px 30px 40px"
, yang menentukan masing-masing 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],
});
<iframe>
ajaib
IntersectionObserver
dirancang khusus dengan mempertimbangkan widget jaringan sosial dan layanan iklan, yang sering menggunakan elemen <iframe>
dan dapat memperoleh manfaat jika mengetahui apakah mereka berada di depan mata. Jika <iframe>
mengamati salah satu elemennya, men-scroll <iframe>
serta men-scroll jendela yang berisi <iframe>
akan memicu callback pada waktu yang tepat. Namun, untuk kasus yang terakhir, rootBounds
akan ditetapkan ke null
untuk menghindari kebocoran data di seluruh origin.
Apa yang dimaksud dengan IntersectionObserver
Bukan?
Perlu diingat bahwa IntersectionObserver
sengaja tidak sempurna dengan piksel atau latensi rendah. Menggunakannya untuk mengimplementasikan upaya seperti animasi yang bergantung pada scroll pasti akan gagal, karena data tersebut akan—secara tegas—sudah tidak berlaku pada saat Anda menggunakannya. Penjelasan ini berisi detail selengkapnya tentang kasus penggunaan asli untuk IntersectionObserver
.
Berapa banyak pekerjaan yang dapat saya lakukan di callback?
Short 'n Sweet: Menghabiskan terlalu banyak waktu di callback akan membuat aplikasi lambat—semua praktik umum berlaku.
Maju dan perpotongan elemen-elemen Anda
Dukungan browser untuk IntersectionObserver
bagus, karena tersedia di semua browser modern. Jika perlu, polyfill dapat digunakan di browser lama dan tersedia di repositori WICG. Tentunya, Anda tidak akan mendapatkan manfaat performa menggunakan polyfill yang akan diberikan oleh implementasi native.
Anda dapat mulai menggunakan IntersectionObserver
sekarang. Beri tahu kami ide Anda.