JavaScript IntersectionObserver — коли елемент з'явився на екрані
IntersectionObserver (спостерігач перетину) повідомляє, коли елемент з'явився в полі зору або зник із нього.
Загальний опис
Раніше це робили обробником scroll: на кожен піксель прокрутки бігали по елементах і рахували координати через getBoundingClientRect(). Це били десятки разів на секунду, перераховували макет і різали продуктивність — сторінка «смикалась» при прокрутці.
Спостерігач працює інакше: він асинхронний і живе поза головним потоком. Браузер сам знає, що куди перетнулось, і просто повідомляє — без жодних обчислень із твого боку.
Звідси три класичні застосування: ліниве завантаження зображень, нескінченна стрічка (спостерігаємо за «маячком» у кінці списку) і анімації появи блоків.
Поріг threshold каже, яку частку елемента вважати видимою: 0 — щойно з'явився край, 1 — видно повністю.
- Порада
-
Одноразові речі (підвантажити картинку, програти анімацію) не забувай знімати:
автор: NagarDobserver.unobserve(element)після спрацювання — інакше платитимеш за спостереження вічно.
Синтаксис
const observer = new IntersectionObserver(callback, options);
властивості
| Властивість | Опис |
|---|---|
| root | Елемент-область перетину (null — вікно). |
| rootMargin | Відступи області перетину. |
| thresholds | Пороги видимості, на яких спрацьовує колбек. |
методи
| Метод | Опис |
|---|---|
| observe | Починає стежити за елементом. |
| unobserve | Припиняє стежити за елементом. |
| disconnect | Припиняє стежити за всіма. |
Переглядачі
| Переглядач | ||||||
|---|---|---|---|---|---|---|
| IntersectionObserver | 51+ | 55+ | 12.1+ | 38+ | 15+ | - |
| Переглядач | ||||
|---|---|---|---|---|
| IntersectionObserver | 51+ | yes | yes | 12.2+ |
Приклади
+ запропонувати свій приклад у пісочниці
Ліниве завантаження й нескінченна стрічка — без обробника scroll.
HTML
<img data-src="/img/logo.svg" alt="">
<div id="sentinel"></div>
JS
const lazy = new IntersectionObserver((entries, observer) => {
for (const entry of entries) {
if (!entry.isIntersecting) {
continue;
}
const img = entry.target;
img.src = img.dataset.src;
// спрацювало один раз — більше не спостерігаємо
observer.unobserve(img);
}
}, {
// почати вантажити за 200px ДО появи на екрані
rootMargin: '200px',
});
document.querySelectorAll('img[data-src]').forEach(img => lazy.observe(img));
// нескінченна стрічка: маячок у кінці списку
const more = new IntersectionObserver(entries => {
if (entries[0].isIntersecting) {
loadNextPage();
}
});
more.observe(document.getElementById('sentinel'));
Коментарі
Коментарів ще немає — будьте першим!