Библиотека AOS (Animate On Scroll) реализует базовую логику
отслеживания появления элементов во viewport с помощью встроенных
механизмов, однако для более гибкого контроля и повышения
производительности целесообразно использовать
Intersection Observer API. Такое комбинирование
позволяет:
Intersection Observer работает асинхронно и не привязан
к событиям прокрутки, что делает его значительно эффективнее
традиционных обработчиков scroll.
AOS автоматически добавляет классы (aos-animate) при
появлении элемента в зоне видимости. При использовании
Intersection Observer можно вручную управлять этим
процессом.
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('aos-animate');
} else {
entry.target.classList.remove('aos-animate');
}
});
}, {
threshold: 0.2
});
document.querySelectorAll('[data-aos]').forEach(el => {
observer.observe(el);
});
threshold определяет процент видимости элементаAOS.init({
disableMutationObserver: true,
startEvent: 'DOMContentLoaded'
});
Чтобы полностью передать контроль Intersection Observer,
необходимо:
AOS.init({
disable: true
});
После этого библиотека используется только как набор CSS-анимаций, а логика триггера полностью управляется вручную.
Intersection Observer позволяет задавать массив значений
threshold, что открывает возможность для сложных
эффектов.
const observer = new IntersectionObserver(callback, {
threshold: [0, 0.25, 0.5, 0.75, 1]
});
if (entry.intersectionRatio > 0.5) {
entry.target.classList.add('half-visible');
}
AOS по умолчанию может запускать анимацию один раз
(once: true). Через Intersection Observer
реализуется полный контроль:
if (entry.isIntersecting) {
entry.target.classList.add('aos-animate');
} else {
entry.target.classList.remove('aos-animate');
}
Дополнительные параметры позволяют управлять областью отслеживания:
const observer = new IntersectionObserver(callback, {
root: null,
rootMargin: '0px 0px -100px 0px'
});
root: контейнер прокрутки (по умолчанию viewport)rootMargin: смещение границКомбинирование позволяет объединить анимацию и lazy-loading:
if (entry.isIntersecting) {
const img = entry.target.querySelector('img');
img.src = img.dataset.src;
entry.target.classList.add('aos-animate');
observer.unobserve(entry.target);
}
AOS требует вызова refresh() при добавлении новых
элементов. При использовании Intersection Observer это
ограничение исчезает.
const newElement = document.createElement('div');
newElement.setAttribute('data-aos', 'fade-up');
document.body.appendChild(newElement);
observer.observe(newElement);
AOS можно использовать только для CSS-анимаций, а
Intersection Observer — для запуска сложной логики.
if (entry.isIntersecting) {
entry.target.classList.add('aos-animate');
// дополнительная логика
startCounter(entry.target);
playVideo(entry.target);
}
observer.unobserve(entry.target);
AOS поддерживает параметры:
<div data-aos="fade-up" data-aos-delay="200" data-aos-duration="1000"></div>
При ручном управлении эти значения остаются актуальными, так как они применяются через CSS.
entry.target.style.transitionDelay = '200ms';
entry.target.style.transitionDuration = '1000ms';
Для анализа поведения элементов полезно логировать состояние:
console.log(entry.intersectionRatio);
console.log(entry.boundingClientRect);
isIntersecting — факт пересеченияintersectionRatio — процент видимостиtarget — наблюдаемый элементintersectionRatiorootMarginОптимальная схема:
Такое разделение ответственности позволяет добиться высокой производительности, гибкости и масштабируемости интерфейса.