Обновление анимаций при смене роутов

Библиотека AOS (Animate on Scroll) предназначена для запуска анимаций элементов при их появлении в области видимости окна браузера. В стандартном сценарии, когда страница загружается полностью, инициализация выполняется один раз с помощью функции AOS.init(). Однако в современных SPA-приложениях (Single Page Application) с использованием роутинга возникает особенность: переход между “страницами” не сопровождается полной перезагрузкой документа, а значит, многие элементы добавляются в DOM после первоначальной инициализации AOS. В этом случае стандартного вызова AOS.init() недостаточно для корректного запуска анимаций на новых элементах.


Основные проблемы при смене роутов

  1. Новые элементы в DOM не анимируются При динамическом рендеринге новых страниц элементы, появляющиеся после первой инициализации AOS, не получают обработчики и классы, необходимые для анимаций.

  2. Повторная анимация старых элементов Если не учитывать текущий статус элементов, повторный вызов AOS.init() может неправильно обработать уже анимированные блоки или вызвать конфликт классов.

  3. Отсутствие автоматического обновления AOS не отслеживает изменения DOM самостоятельно — требуется явный вызов метода обновления для пересчета позиций и активации новых элементов.


Методы обновления анимаций

Библиотека предоставляет несколько подходов для корректной работы с динамически изменяющимся контентом.

1. Повторная инициализация

AOS.init({
  once: true,
  duration: 800
});

Если SPA использует роутинг, необходимо повторно вызывать AOS.init() после загрузки нового компонента или маршрута.

Недостаток: стандартный вызов может перезаписать уже анимированные элементы, если не установлен параметр once: true.

2. Использование метода AOS.refresh()

// После изменения DOM
AOS.refresh();

Метод refresh() пересчитывает позиции всех элементов с атрибутом data-aos и применяет анимации к новым блокам без повторного применения к старым. Этот метод оптимален для SPA.

Пример с роутером Vue.js:

import AOS from 'aos';
import 'aos/dist/aos.css';

export default {
  watch: {
    '$route'(to, from) {
      this.$nextTick(() => {
        AOS.refresh();
      });
    }
  }
}

Здесь используется this.$nextTick() для того, чтобы убедиться, что новые элементы полностью отрисованы в DOM до вызова AOS.refresh().

3. Метод AOS.refreshHard()

AOS.refreshHard();

refreshHard() полностью пересоздаёт внутренние данные AOS, включая удаление и повторное создание всех обработчиков. Рекомендуется использовать только при крупных изменениях DOM, так как этот метод более затратный по производительности.


Настройка параметров для SPA

Для корректной работы анимаций в приложениях с роутингом рекомендуется установить следующие параметры при инициализации:

AOS.init({
  disable: 'mobile',   // Отключение анимаций на мобильных устройствах для производительности
  once: true,          // Элемент анимируется только один раз
  mirror: false,       // Элемент не будет анимироваться при скролле назад
  duration: 700,       // Длительность анимации
  easing: 'ease-in-out'
});
  • once: true предотвращает повторное срабатывание анимаций на уже просмотренных элементах.
  • mirror: false предотвращает повторную анимацию при прокрутке вверх, что снижает нагрузку на браузер.

Рекомендованный подход при интеграции с React, Vue и Angular

  1. React Вызывать AOS.refresh() внутри useEffect, который зависит от изменения маршрута:
import { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
import { useLocation } from 'react-router-dom';

function App() {
  const location = useLocation();

  useEffect(() => {
    AOS.init({ once: true, duration: 700 });
    AOS.refresh();
  }, [location.pathname]);

  return <Routes>...</Routes>;
}
  1. Vue.js Как показано выше, использовать watch на $route с вызовом AOS.refresh() после полной отрисовки компонента.

  2. Angular В Angular рекомендуется использовать хук ngAfterViewInit() или подписку на событие маршрута NavigationEnd:

import { Component, AfterViewInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import AOS from 'aos';

@Component({...})
export class AppComponent implements AfterViewInit {
  constructor(private router: Router) {}

  ngAfterViewInit() {
    AOS.init({ once: true, duration: 700 });

    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd) {
        setTimeout(() => AOS.refresh(), 0);
      }
    });
  }
}

setTimeout гарантирует, что DOM полностью обновлен перед пересчетом позиций.


Практические рекомендации

  • Использовать AOS.refresh() для динамически добавляемого контента.
  • Избегать частого вызова AOS.init() после каждого роутинга — лучше инициализировать один раз и использовать refresh().
  • Для больших приложений с бесконечным скроллом комбинировать AOS.refresh() с виртуальным скроллингом, чтобы минимизировать перерисовку.
  • Настраивать once и mirror для контроля повторных анимаций и производительности.

Обновление анимаций при смене роутов является ключевым моментом для SPA, позволяя поддерживать плавные и корректные эффекты без перезагрузки страницы.