Intersection Observer
Intersection observer adalah API dari javascript untuk mengamati apakah suatu element berada dalam viewport.

Mendeteksi suatu element apakah telah terlihat dalam viewport harus dilakukan manual, apalagi terdapat berbagai trik dan issue soal performanya. Setidaknya begitu, sebelum Intersection Observer API rilis dalam chromium versi 51. Ini memungkinkan kita untuk melakukan beberapa hal dalam konteks di atas, termasuk di dalamnya pengurangan penggunaan CPU sehingga meningkatkan performa dan pengalaman pengguna.
Dalam lebih banyak kasus, kita mungkin membutuhkan intersection observer untuk menyelesaikannya. Termasuk image lazy load, infinite scrolling dan melakukan tugas atau animasi ketika element tertentu memasuki viewport.

Bagaimana membuat intersection observer API
Jika dulu mengimplementasi pendeteksi dalam viewport melibatkan event handler dan terus mengulangi pemanggilan method untuk mengetahui informasi setiap kali element terlihat.
Menggunakan intersection observer hanya menuliskan beberapa baris kode, dengan memanggil constructornya IntersectionObserver()
dan memasukkan callback juga options yang dibutuhkan.
let options = {
root: null,
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options)
Intersection observer options
Options yang dimasukkan ke constructor IntersectionObserver()
memungkinkan kita dapat mengontrol keadaan di mana callback akan dipanggil.
Root
Value yang dimasukkan dalam opsi root adalah parent element dan berguna sebagai penentu visibilitas. Bisa document.getElementById('scroll-area')
atau menggunakan defaultnya yaitu null
rootMargin
Seperti namanya, property ini akan berada sekitar root/parent target. rootMargin
akan memiliki value seperti dalam css, '10px 20% 30px 40%'
dan akan mempengaruhi margin dari element root itu sendiri. Default propertynya adalah “0px”.
threshold
Threshold memiliki value number atau array of number, sebagai penunjuk berapa persentase visibilitas target dan kapan callback harus dijalankan. Ketika ingin target terdeteksi ketika mencapai 50% dalam viewport, maka value yang harus dimasukkan adalah 0.5
. Atau jika ingin terdeteksi setiap 25% dari target, value harus berupa array of number [0, 0.25, 0.50, 0.75, 1.0]
.
Default property ini adalah 0
, dan callback akan dijalankan apabila setiap pixel dari target terlihat. Gunakan 1.0
jika ingin callback dijalankan ketika seluruh target berada dalam viewport.
Contoh
Dalam contoh kali ini, kita akan mencoba membuat kotak yang akan dianimasikan apabila telah terlihat dalam viewport.
HTML
Disini kita hanya membutuhkan 3 baris utama kode HTML.
<div class="container">
<div class="box"></div>
</div>
CSS
Kode CSS ini hanya terdapat layout, warna background dan transisi untuk mengetahui visibilitas element.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow-x: hidden;
}
.container {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 250vh;
perspective: 1000px;
}
.box {
height: 500px;
width: 500px;
object-fit: cover;
object-position: center;
background: lightblue;
transition: 500ms ease-in-out;
opacity: 0;
transform-style: preserve-3d;
}
.animate {
background: rgb(55, 150, 182);
opacity: 1 !important;
transform: rotateY(180deg);
}
JavaScript
Dan untuk kode javascript, pertama kita membutuhkan target dan juga options intersection observer.
const element = document.querySelector(".box")
const options = {
root: null,
rootMargin: '0px',
threshold: 0.45
}
Dalam object options, terdapat 3 property utama yang dibutuhkan.
Value null
menunjukan visibilitas target yang relative terhadap viewport. Sedang rootMargin: '0px'
karena kita tidak membutuhkannya.
Kemudian yang terakhir adalah threshold: 0.45
, itu akan membuat target terdeteksi apabila 45%
bagian darinya terlihat dalam viewport.
const callback = (entries, observer) => {
const [ entry ] = entries
if (entry.isIntersecting) {
entry.target.classList.add("animate")
} else {
entry.target.classList.remove("animate")
}
}
Callback diatas akan dijalankan setiap kali browser mendeteksi perubahan visibilitas target. Karena entries
merupakan array
, kita destructure terlebih dahulu dan mendapatkan informasi dari target dan setiap perubahan viewport yang dilakukan.
const observer = new IntersectionObserver(callback, options)
observer.observe(element)
Dan yang terakhir, kita masukkan callback dan options ke dalam constructor IntersectionObserver()
. Kemudian kita panggil method observe()
dengan memasukkan target element yang kita inginkan.
Complete Code
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow-x: hidden;
}
.container {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 250vh;
perspective: 1000px;
}
.box {
height: 500px;
width: 500px;
object-fit: cover;
object-position: center;
background: lightblue;
transition: 500ms ease-in-out;
opacity: 0;
transform-style: preserve-3d;
}
.animate {
background: rgb(55, 150, 182);
opacity: 1 !important;
transform: rotateY(180deg);
}
</style>
<title>Intersection Observer</title>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
<script>
const element = document.querySelector(".box")
const options = {
root: null,
rootMargin: '0px',
threshold: 0.45
}
const callback = (entries, observer) => {
const [ entry ] = entries
if (entry.isIntersecting) {
entry.target.classList.add("animate")
} else {
entry.target.classList.remove("animate")
}
}
const observer = new IntersectionObserver(callback, options)
observer.observe(element)
</script>
</body>
</html>
Akhir kata
Jadi begitulah sedikit pengenalan IntersectionObserver API yang memudahkan kita untuk membangun modern web apps.
Terimakasih.