Создание интерактивных переходов

Интерактивные переходы — это анимации, которые реагируют на действия пользователя: наведение курсора, клики, прокрутку, ввод данных. В контексте библиотеки anime.js такие переходы строятся на сочетании событий DOM и анимационных конфигураций.

Ключевая идея — связать событие и анимацию, обеспечив плавную реакцию интерфейса на действия.

Основные типы взаимодействий:

  • hover (наведение)
  • click (клик)
  • scroll (прокрутка)
  • drag (перетаскивание)
  • input (ввод)

Базовая структура интерактивной анимации

Типичный сценарий включает три элемента:

  1. Выбор DOM-элемента
  2. Назначение обработчика события
  3. Запуск анимации через anime.js
const button = document.querySelector('.btn');

button.addEventListener('mouseenter', () => {
  anime({
    targets: button,
    scale: 1.1,
    duration: 300,
    easing: 'easeOutQuad'
  });
});

button.addEventListener('mouseleave', () => {
  anime({
    targets: button,
    scale: 1,
    duration: 300,
    easing: 'easeOutQuad'
  });
});

Реакция на наведение (hover)

Hover-анимации используются для создания мгновенной визуальной обратной связи.

Изменение цвета и масштаба

anime({
  targets: '.card',
  backgroundColor: '#ffcc00',
  scale: 1.05,
  duration: 400,
  easing: 'easeOutCubic',
  autoplay: false
});

Для интерактивности необходимо управлять запуском:

const cards = document.querySelectorAll('.card');

cards.forEach(card => {
  const animation = anime({
    targets: card,
    scale: 1.05,
    duration: 300,
    autoplay: false
  });

  card.addEventListener('mouseenter', animation.play);
  card.addEventListener('mouseleave', animation.reverse);
});

Особенность: метод reverse() позволяет воспроизводить анимацию в обратном направлении, что упрощает управление состояниями.

Анимации при клике

Клик — основной триггер для сложных переходов.

Пример: эффект нажатия кнопки

const btn = document.querySelector('.btn');

btn.addEventListener('click', () => {
  anime.timeline()
    .add({
      targets: btn,
      scale: 0.9,
      duration: 100
    })
    .add({
      targets: btn,
      scale: 1,
      duration: 200,
      easing: 'easeOutElastic(1, .5)'
    });
});

Переключение состояний

let active = false;

btn.addEventListener('click', () => {
  active = !active;

  anime({
    targets: '.menu',
    translateX: active ? 0 : '-100%',
    duration: 500,
    easing: 'easeInOutQuad'
  });
});

Ключевой момент: хранение состояния вне анимации позволяет управлять интерфейсом предсказуемо.

Интерактивные переходы при прокрутке

anime.js не имеет встроенного scroll-движка, но легко интегрируется с событиями прокрутки.

Простой пример

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY;

  anime({
    targets: '.header',
    translateY: scrollY > 100 ? -80 : 0,
    duration: 300,
    easing: 'easeOutQuad'
  });
});

Связь анимации с позицией скролла

window.addEventListener('scroll', () => {
  const progress = window.scrollY / 500;

  anime.set('.box', {
    translateX: progress * 300
  });
});

anime.set() позволяет мгновенно обновлять значения без анимации — важно для синхронизации с прокруткой.

Плавные переходы между состояниями

Интерактивные интерфейсы часто требуют анимации между двумя состояниями элемента.

Пример: раскрывающийся блок

const toggle = document.querySelector('.toggle');
const panel = document.querySelector('.panel');

let open = false;

toggle.addEventListener('click', () => {
  open = !open;

  anime({
    targets: panel,
    height: open ? 200 : 0,
    opacity: open ? 1 : 0,
    duration: 400,
    easing: 'easeInOutQuad'
  });
});

Автоматическое вычисление высоты

const contentHeight = panel.scrollHeight;

anime({
  targets: panel,
  height: open ? contentHeight : 0
});

Использование timeline для сложных переходов

Timeline позволяет строить последовательные и синхронизированные анимации.

const tl = anime.timeline({
  autoplay: false
});

tl.add({
  targets: '.overlay',
  opacity: [0, 1],
  duration: 300
}).add({
  targets: '.modal',
  translateY: [-50, 0],
  opacity: [0, 1],
  duration: 400
}, '-=200');

Запуск по событию:

document.querySelector('.open').addEventListener('click', () => {
  tl.play();
});

Закрытие:

document.querySelector('.close').addEventListener('click', () => {
  tl.reverse();
});

Преимущество: единый контроль над всей цепочкой анимаций.

Интерактивность через параметры функции

anime.js поддерживает динамические значения.

anime({
  targets: '.item',
  translateX: (el, i) => i * 50,
  delay: (el, i) => i * 100
});

Реакция на позицию курсора

document.addEventListener('mousemove', (e) => {
  anime({
    targets: '.cursor',
    left: e.clientX,
    top: e.clientY,
    duration: 100,
    easing: 'linear'
  });
});

Перетаскивание и физическая интерактивность

Для drag-интеракций используется комбинация событий мыши.

const box = document.querySelector('.box');

let isDragging = false;

box.addEventListener('mousedown', () => {
  isDragging = true;
});

document.addEventListener('mouseup', () => {
  isDragging = false;
});

document.addEventListener('mousemove', (e) => {
  if (!isDragging) return;

  anime.set(box, {
    translateX: e.clientX,
    translateY: e.clientY
  });
});

Плавность и естественность

Ключевые параметры:

  • easing
  • duration
  • delay

Примеры easing-функций

easing: 'easeOutElastic(1, .5)'
easing: 'easeInOutQuad'
easing: 'cubicBezier(.5, .05, .1, .3)'

Рекомендации:

  • быстрые реакции: 150–300 мс
  • переходы состояний: 300–600 мс
  • сложные анимации: до 1000 мс

Управление производительностью

Интерактивные анимации могут вызывать лаги при неправильной реализации.

Оптимизации:

  • использовать transform вместо top/left
  • избегать частого создания новых анимаций
  • применять anime.set() для мгновенных обновлений
  • дебаунсить scroll и mousemove
let ticking = false;

window.addEventListener('scroll', () => {
  if (!ticking) {
    requestAnimationFrame(() => {
      // анимация
      ticking = false;
    });
    ticking = true;
  }
});

Комбинирование CSS и anime.js

Часть эффектов удобнее реализовать через CSS, а anime.js использовать для логики.

.box {
  transition: background-color 0.3s;
}
box.addEventListener('mouseenter', () => {
  box.style.backgroundColor = 'red';
});

anime.js добавляет:

  • сложные переходы
  • последовательности
  • динамические вычисления

Архитектура интерактивных переходов

Хорошая практика — разделение:

  • логики (события)
  • состояния
  • анимации
function openMenu() {
  return anime({
    targets: '.menu',
    translateX: 0
  });
}

function closeMenu() {
  return anime({
    targets: '.menu',
    translateX: '-100%'
  });
}

Такой подход:

  • упрощает поддержку
  • позволяет переиспользовать анимации
  • облегчает тестирование

Интеграция с интерфейсами

Интерактивные переходы особенно эффективны в:

  • SPA-приложениях
  • модальных окнах
  • навигационных меню
  • карточных интерфейсах
  • дашбордах

anime.js обеспечивает:

  • декларативное описание
  • гибкость
  • высокую точность управления

За счёт этого интерактивные переходы становятся не просто визуальным эффектом, а инструментом улучшения пользовательского опыта и навигации.