Библиотека AOS (Animate On Scroll) ориентирована на декларативные CSS-анимации, активируемые при появлении элементов в зоне видимости. В свою очередь, ScrollMagic предоставляет более низкоуровневый контроль над прокруткой: управление сценами, синхронизация с таймлайнами, закрепление (pinning) элементов и сложные сценарии анимации.
Совместное использование позволяет:
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.4/dist/aos.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js"></script>
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
Инициализация:
AOS.init({
duration: 800,
once: false
});
const controller = new ScrollMagic.Controller();
AOS отслеживает появление элементов через собственный обработчик
скролла. ScrollMagic работает через сцены (Scene), которые
определяют:
Чтобы связать их, используется принудительное обновление AOS:
scene.on("enter", () => {
AOS.refresh();
});
HTML:
<div id="trigger"></div>
<div data-aos="fade-up" id="box">
Контент
</div>
JS:
const scene = new ScrollMagic.Scene({
triggerElement: "#trigger",
triggerHook: 0.8,
reverse: true
})
.on("enter", () => {
document.querySelector("#box").classList.add("aos-animate");
})
.on("leave", () => {
document.querySelector("#box").classList.remove("aos-animate");
})
.addTo(controller);
aos-animate — класс, который AOS добавляет
автоматическиЧтобы полностью передать контроль ScrollMagic, необходимо отключить автоинициализацию:
AOS.init({
startEvent: 'DOMContentLoaded',
disableMutationObserver: true
});
И не использовать стандартный scroll listener AOS, а управлять классами вручную.
ScrollMagic позволяет отслеживать прогресс сцены:
scene.on("progress", (event) => {
const progress = event.progress;
const element = document.querySelector("#box");
element.style.transform = `translateY(${100 - progress * 100}px)`;
element.style.opacity = progress;
});
AOS задает начальные стили, ScrollMagic — управляет переходом:
[data-aos="custom"] {
opacity: 0;
transform: translateY(100px);
transition: all 0.3s ease;
}
scene.on("progress", (event) => {
const el = document.querySelector("[data-aos='custom']");
el.style.opacity = event.progress;
});
ScrollMagic поддерживает закрепление элементов:
new ScrollMagic.Scene({
triggerElement: "#section",
duration: 500
})
.setPin("#pinned-element")
.addTo(controller);
При использовании pin:
Принудительное обновление:
scene.on("enter", () => AOS.refreshHard());
AOS по умолчанию работает с window. ScrollMagic
позволяет использовать кастомный контейнер:
const controller = new ScrollMagic.Controller({
container: "#scroll-container"
});
AOS не отслеживает кастомные контейнеры.
Принудительный вызов обновления:
document.querySelector("#scroll-container").addEventListener("scroll", () => {
AOS.refresh();
});
AOS поддерживает повторное воспроизведение, но при интеграции со ScrollMagic это нужно контролировать явно:
scene.on("leave", () => {
const el = document.querySelector("#box");
el.classList.remove("aos-animate");
});
AOS.refresh()Частые вызовы приводят к перерасчету layout:
let ticking = false;
window.addEventListener("scroll", () => {
if (!ticking) {
requestAnimationFrame(() => {
AOS.refresh();
ticking = false;
});
ticking = true;
}
});
Каждая сцена ScrollMagic:
Рекомендуется:
ScrollMagic часто используется вместе с GSAP. В этом случае AOS может выполнять роль “простых” эффектов, а GSAP — сложных.
const tween = gsap.to("#box", {
x: 200,
opacity: 1
});
new ScrollMagic.Scene({
triggerElement: "#box",
duration: 300
})
.setTween(tween)
.addTo(controller);
Причины:
Решение:
AOS.refreshHard();
Причины:
Решение:
AOS использует CSS transition, ScrollMagic — JS.
Решение:
progress<section id="section">
<div id="trigger"></div>
<div id="box" data-aos="fade-up">
Контент
</div>
</section>
AOS.init({
duration: 600,
once: false
});
const controller = new ScrollMagic.Controller();
const scene = new ScrollMagic.Scene({
triggerElement: "#trigger",
duration: 400,
triggerHook: 0.7
})
.on("enter", () => {
document.querySelector("#box").classList.add("aos-animate");
})
.on("progress", (e) => {
const el = document.querySelector("#box");
el.style.transform = `scale(${0.8 + e.progress * 0.2})`;
})
.on("leave", () => {
document.querySelector("#box").classList.remove("aos-animate");
})
.addTo(controller);
В данной конфигурации:
fade-up)