Pengamat Persimpangan | Membuat scroll tak terbatas di aplikasi web Anda

Nov 25 2022
Jika Anda bukan orang gua atau Anda tidak membenci Jeff Bezos (tidak masalah meskipun Anda membencinya), Anda pasti pernah berbelanja online. Saat Anda mencari barang di toko online ini, Anda akan disajikan daftar hasil.
Foto oleh SpaceX di Unsplash

Jika Anda bukan orang gua atau Anda tidak membenci Jeff Bezos (tidak masalah meskipun Anda membencinya), Anda pasti pernah berbelanja online. Saat Anda mencari barang di toko online ini, Anda akan disajikan daftar hasil. Jika Anda tidak aneh seperti saya dan tidak mencari “ gigi harimau berlumuran darah manusia” yang terlalu spesifik, ada kemungkinan permintaan pencarian Anda akan mendapatkan ribuan produk. Apakah menurut Anda browser Anda memuat semua 1000+ item ini sekaligus? Tidak , itu akan menjadi terlalu banyak data bagi browser untuk menangani dan menghitung antarmuka pengguna. Tetap saja, Anda terus mendapatkan item saat Anda terus mencapai hasil akhir. Ini disebut gulir tak terbatas .

Berikut adalah contoh infinte scroll di beranda YouTube.

Gif menjelaskan gulir tak terbatas

Ada beberapa teknik untuk mencapai ini dengan menggunakan JavaScript, tetapi yang paling efisien menggunakan api web manis yang disebut IntersectionObserver. Mari kita lihat cara menggunakan API ini untuk mengimplementasikan daftar mini yang dapat digulir tak terbatas milik kita sendiri.

Konsepnya adalah, mengamati elemen html setiap kali muncul di area pandang dan kemudian memicu panggilan balik. Inilah cara membuat pengamat ini.

Mari buat file html yang terlihat seperti ini.

<!DOCTYPE html>
<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">
    <title>Infinte Scroll</title>
</head>
<style>
    .product {
        padding: 20px;
        border: 1px solid black;
        margin-bottom: 20px;
        opacity: 0;
        margin-left: 100px;
        transition: all 300ms;
    }
    .visible {
        opacity: 1;
        margin-left: 0px;
    }
</style>
<body>
    <div id="container">
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
        <div class="product">Product</div>
    </div>

    <script src="./index.js"></script>
</body>
</html>

Pertama mari kita dapatkan semua kartu produk dengan nama kelasnya

const cards = document.querySelectorAll('.product');

const productCards= document.querySelectorAll('.product');

const observer = new IntersectionObserver((entries) => {
    // Todo
}, {
    threshold: 0.95,
});

productCards.forEach((card) => {
  observer.observe(card);
})

Parameter lain dalam konstruktor adalah objek. Objek ini menandakan opsi untuk pengamat khusus ini. Dalam hal ini, kami hanya memiliki ambang batas. ambang di sini adalah angka yang dapat mengambil nilai apa pun dari 0 hingga 1. Ini menandakan persentase item yang kami amati yang harus terlihat di viewport agar dianggap berpotongan. kami telah memberinya nilai 0,95 yang berarti ketika 95% dari setiap kartu produk masuk ke area pandang, kartu tersebut akan dianggap berpotongan dengan area pandang.

Mari kembali ke file index.html kita . Kami juga memiliki kelas gaya lain yang terlihat ditentukan dalam tag gaya. Gaya ini, ketika diterapkan pada kartu produk kita, akan membuat kartu terlihat lagi dengan sedikit animasi ( properti transisi ).

Mari kita buat perubahan pada pengamat kita sehingga semua kartu produk yang setidaknya 95% di area pandang akan terlihat dan sisanya akan disembunyikan.

const productCards = document.querySelectorAll('.product');

const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        entry.target.classList.toggle('visible', entry.isIntersecting);
    })
}, {
    threshold: 0.95
});

productCards.forEach((card) => {
    observer.observe(card);
});

Namun ada satu tangkapan. Saat kami menggulir ke atas, karena kami memiliki logika untuk mengaktifkan kelas yang terlihat saat item berpotongan, kelas ini juga akan dihapus jika tidak. Jadi, saat kami menggulir ke atas, kami melihat kartu kami menghilang dari atas. Untuk memperbaikinya, kami akan berhenti mengamati kartu yang sudah berpotongan.

const productCards = document.querySelectorAll('.product');

const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        entry.target.classList.toggle('visible', entry.isIntersecting);
        // unobserving entries which have already intersected
        if (entry.isIntersecting) observer.unobserve(entry.target);
    })
}, {
    threshold: 0.95
});

productCards.forEach((card) => {
    observer.observe(card);
});

Pertama, kita akan membuat pengamat lain yang hanya akan mengamati kartu terakhir.

const lastCardObserver = new IntersectionObserver((entries) => {
    const lastCard = entries[0];
    if (!lastCard.isIntersecting) return;
    loadMoreCards();
    lastCardObserver.unobserve(lastCard.target);
    lastCardObserver.observe(document.querySelector('.product:last-child'));
}, {
    threshold: 0.95
});

lastCardObserver.observe(document.querySelector('.product:last-child'));

function loadMoreCards() {
    const container = document.getElementById('container');
    for (let i = 0; i < 10; i++) {
        const element = document.createElement('div');
        element.classList.add('product');
        element.innerText = 'Product';
        observer.observe(element);
        container.appendChild(element);
    }
}

Begini tampilannya sekarang!

Gulir Tak Terbatas Sempurna!

Sekarang, dalam aplikasi dunia nyata, alih-alih memuat lebih banyak kartu, kami akan mengambil data baru menggunakan API.

Beri tahu saya bagaimana Anda dapat menggunakan API ini secara kreatif dalam aplikasi Anda.