Intersection Observer

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

August 10, 2021 - 4 min read

Intersection image from unsplash

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.

Cara cek apakah browser support Intersection Observer

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.

Kamu mungkin juga suka.