Obserwator skrzyżowania | Tworzenie nieskończonego przewijania w Twojej aplikacji internetowej
Jeśli nie jesteś jaskiniowcem lub nie nienawidzisz Jeffa Bezosa (nieważne, czy tak jest), na pewno robiłeś zakupy online. Gdy szukasz artykułu w tych sklepach internetowych, wyświetlana jest lista wyników. Jeśli nie jesteś dziwakiem jak ja i nie szukasz zbyt szczegółowego hasła „ tygrysi ząb nasączony ludzką krwią” , jest szansa, że Twoje zapytanie wygeneruje tysiące produktów. Czy myślisz, że Twoja przeglądarka ładuje razem te ponad 1000 elementów? Nie , to byłoby zbyt dużo danych, aby przeglądarka mogła obsłużyć i obliczyć interfejs użytkownika. Mimo to nadal otrzymujesz przedmiot, gdy zbliżasz się do końca swojego wyniku. Nazywa się to nieskończonym przewijaniem .
Oto przykład przewijania w nieskończoność na stronie głównej YouTube.

Istnieje kilka technik, aby to osiągnąć za pomocą JavaScript, ale najskuteczniejsza jest użycie słodkiego internetowego interfejsu API o nazwie IntersectionObserver. Zobaczmy, jak użyć tego interfejsu API do zaimplementowania naszej własnej mini nieskończonej przewijanej listy.
Koncepcja polega na obserwowaniu elementu HTML za każdym razem, gdy pojawia się on w rzutni, a następnie wyzwalaniu wywołania zwrotnego. Oto jak utworzyć tego obserwatora.
Stwórzmy plik html, który wygląda tak.
<!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>
Najpierw pobierzmy wszystkie karty produktów według ich nazw klas
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);
})
Kolejnym parametrem w konstruktorze jest obiekt. Obiekt ten oznacza opcje dla tego konkretnego obserwatora. W tym przypadku mamy tylko próg. próg jest tutaj liczbą, która może przyjąć dowolną wartość od 0 do 1. Oznacza to, jaki procent obserwowanego elementu powinien być widoczny w rzutni, aby można go było uznać za przecinający się. nadaliśmy jej wartość 0,95, co oznacza, że gdy 95% dowolnej karty produktu pojawi się w oknie roboczym, karta ta zostanie uznana za przecinającą okno robocze.
Wróćmy do naszego pliku index.html . Mamy też inną widoczną klasę stylu zdefiniowaną w tagu styled. Ten styl zastosowany do naszej karty produktu sprawi, że karta będzie ponownie widoczna z niewielką animacją ( właściwość przejściowa ).
Wprowadźmy zmiany w naszym obserwatorze tak, aby wszystkie karty produktów, które mają co najmniej 95% w oknie podglądu były widoczne, a reszta była ukryta.
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);
});

Jest jednak jeden haczyk. Kiedy przewijamy w górę, ponieważ mamy logikę przełączania widocznej klasy, gdy element się przecina, usuwa ona również tę klasę, gdy nie jest. Tak więc, kiedy przewijamy w górę, widzimy, jak nasze karty znikają z góry. Aby to naprawić, przestaniemy obserwować karty, które już się przecięły.
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);
});
Najpierw stworzymy kolejnego obserwatora, który będzie obserwował ostatnią kartę.
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);
}
}
Tak to teraz wygląda!

Idealny nieskończony zwój!
Teraz w rzeczywistych aplikacjach, zamiast ładować kolejne karty, będziemy pobierać nowe dane za pomocą API.
Daj mi znać, jak możesz kreatywnie wykorzystać ten interfejs API w swoich aplikacjach.