Анимации появления и исчезновения элементов

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


Контроллеры и действия

Для работы с анимациями создаются контроллеры. Контроллер — это класс, наследуемый от Stimulus.Controller, который связывается с DOM-элементом через атрибут data-controller. Действия элемента (actions) позволяют отслеживать события, инициирующие анимацию.

Пример базового контроллера:

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["element"];

  show() {
    this.elementTarget.classList.add("visible");
    this.elementTarget.classList.remove("hidden");
  }

  hide() {
    this.elementTarget.classList.add("hidden");
    this.elementTarget.classList.remove("visible");
  }
}

HTML-структура:

<div data-controller="fade">
  <div data-fade-target="element" class="hidden">Контент для анимации</div>
  <button data-action="click->fade#show">Показать</button>
  <button data-action="click->fade#hide">Скрыть</button>
</div>

Использование CSS-классов для анимации

Stimulus сам по себе не реализует анимации, но отлично интегрируется с CSS-переходами. Для появления и исчезновения элементов применяются классы:

.hidden {
  opacity: 0;
  transition: opacity 0.5s ease-out;
  pointer-events: none;
}

.visible {
  opacity: 1;
  transition: opacity 0.5s ease-in;
}

transition обеспечивает плавное изменение свойств, а управление классами через контроллер запускает анимацию. Ключевой момент: разделение логики отображения (JavaScript) и анимации (CSS) повышает гибкость и упрощает поддержку.


Плавное скрытие с задержкой удаления из DOM

Часто требуется не только скрыть элемент визуально, но и удалить его из DOM после завершения анимации. Для этого используется событие transitionend:

hide() {
  this.elementTarget.classList.add("hidden");
  this.elementTarget.addEventListener("transitionend", () => {
    this.elementTarget.remove();
  }, { once: true });
}

Использование { once: true } гарантирует, что обработчик сработает один раз и автоматически удалится, предотвращая утечки памяти.


Анимации при подключении элемента

Stimulus предоставляет методы жизненного цикла контроллера. Метод connect() вызывается при инициализации контроллера, что позволяет запускать анимацию при появлении элемента на странице:

connect() {
  this.elementTarget.classList.add("hidden");
  requestAnimationFrame(() => {
    this.elementTarget.classList.add("visible");
    this.elementTarget.classList.remove("hidden");
  });
}

requestAnimationFrame обеспечивает корректное срабатывание переходов, гарантируя, что браузер сначала применит начальное состояние (hidden), а затем плавно перейдет к visible.


Сложные последовательности анимаций

Для создания цепочек анимаций используется сочетание таймеров и событий transitionend. Например, последовательное появление нескольких элементов:

showSequence() {
  this.elementTargets.forEach((el, index) => {
    setTimeout(() => {
      el.classList.add("visible");
      el.classList.remove("hidden");
    }, index * 200); // задержка 200ms между элементами
  });
}

В static targets можно определить массив элементов, которые будут анимироваться в порядке DOM.


Интеграция с анимационными библиотеками

Stimulus совместим с библиотеками вроде GSAP или Anime.js, позволяя управлять сложными анимациями через контроллеры:

import { Controller } from "@hotwired/stimulus";
import gsap from "gsap";

export default class extends Controller {
  static targets = ["element"];

  show() {
    gsap.to(this.elementTarget, { opacity: 1, y: 0, duration: 0.5 });
  }

  hide() {
    gsap.to(this.elementTarget, { opacity: 0, y: -20, duration: 0.5 });
  }
}

Преимущество такого подхода — точный контроль над временными кривыми и эффектами, недоступными стандартным CSS.


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

  • Разделение логики и стилей: анимация через CSS, управление состоянием через Stimulus.
  • Использование жизненного цикла контроллера: connect(), disconnect() и initialize() позволяют запускать и останавливать анимации корректно.
  • Очистка обработчиков событий: для предотвращения утечек памяти всегда использовать { once: true } или удалять слушатели в disconnect().
  • Плавные цепочки анимаций: комбинировать задержки, массивы целей и события переходов для последовательных эффектов.

Stimulus обеспечивает структурированное и легковесное управление анимациями, позволяя создавать как простые появления/исчезновения, так и сложные интерактивные последовательности без избыточного кода.