Stimulus — это лёгкий JavaScript-фреймворк, ориентированный на добавление динамики в HTML без необходимости кардинальной перестройки фронтенд-архитектуры. Основная идея заключается в связывании контроллеров с элементами DOM через специальные атрибуты, что позволяет управлять поведением элементов напрямую из JavaScript. При работе с CSS-анимациями этот подход позволяет комбинировать декларативные стили и программное управление их запуском и завершением.
Контроллер Stimulus — это класс, который наследует
Controller из пакета @hotwired/stimulus. В
контексте анимаций он может содержать методы для запуска, остановки и
перезапуска анимаций на элементах DOM.
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
static targets = ["box"];
connect() {
this.boxTarget.classList.add("ready");
}
animate() {
this.boxTarget.classList.add("animate");
this.boxTarget.addEventListener("animationend", () => {
this.boxTarget.classList.remove("animate");
}, { once: true });
}
}
Ключевые моменты:
static targets — определяет элементы внутри
контроллера, с которыми будет происходить взаимодействие.connect() вызывается автоматически при
подключении контроллера к DOM. Здесь удобно добавлять начальные
состояния для анимаций.animationend используется для отслеживания конца
CSS-анимации и снятия классов, чтобы анимацию можно было запустить
повторно.CSS-анимации определяются через ключевые кадры
(@keyframes) и классы, которые будут применяться
динамически из контроллера.
.box {
width: 100px;
height: 100px;
background-color: #3498db;
transition: transform 0.5s ease, opacity 0.5s ease;
opacity: 0;
transform: translateY(20px);
}
.box.ready {
opacity: 1;
transform: translateY(0);
}
.box.animate {
animation: bounce 1s ease forwards;
}
@keyframes bounce {
0% { transform: translateY(0); }
50% { transform: translateY(-30px); }
100% { transform: translateY(0); }
}
Особенности подхода:
.ready задаёт базовое состояние элемента после
подключения к DOM..animate запускает анимацию при
необходимости.animationend позволяет
синхронизировать JavaScript с завершением CSS-анимации, что критично для
повторного воспроизведения и сложных последовательностей.Stimulus позволяет определить несколько targets и управлять ими одновременно или по отдельности:
static targets = ["item"];
animateAll() {
this.itemTargets.forEach(el => {
el.classList.add("animate");
el.addEventListener("animationend", () => {
el.classList.remove("animate");
}, { once: true });
});
}
Такой подход особенно полезен для списков и сеток, где анимации должны запускаться поочерёдно или одновременно.
Stimulus облегчает привязку анимаций к событиям через data-action:
<div data-controller="animation">
<div data-animation-target="box" class="box"></div>
<button data-action="click->animation#animate">Запустить анимацию</button>
</div>
data-action="click->animation#animate"
указывает, что при клике вызывается метод animate
контроллера animation.Для создания цепочек анимаций удобно использовать
setTimeout или animationend:
animateSequence() {
this.itemTargets.forEach((el, index) => {
setTimeout(() => {
el.classList.add("animate");
el.addEventListener("animationend", () => {
el.classList.remove("animate");
}, { once: true });
}, index * 200);
});
}
Такой метод позволяет создавать эффект ступенчатого появления элементов, что часто используется в списках, галереях и интерактивных интерфейсах.
Stimulus предоставляет методы для упрощённого манипулирования классами и атрибутами:
toggleAnimation() {
this.boxTarget.classList.toggle("animate");
}
toggle() упрощает повторное включение и
отключение анимаций.animationend гарантирует корректное
сбрасывание состояния, что предотвращает «залипание» анимации.Stimulus не конфликтует с внешними CSS-библиотеками (например, Animate.css). Контроллер может динамически добавлять классы:
import "animate.css";
animateWithLibrary() {
this.boxTarget.classList.add("animate__animated", "animate__bounce");
this.boxTarget.addEventListener("animationend", () => {
this.boxTarget.classList.remove("animate__animated", "animate__bounce");
}, { once: true });
}
Это позволяет использовать готовые анимации и комбинировать их с собственными состояниями элементов.
Stimulus поддерживает values, что делает контроллер более гибким:
static values = {
duration: Number
};
animate() {
this.boxTarget.style.animationDuration = `${this.durationValue}s`;
this.boxTarget.classList.add("animate");
}
durationValue можно задать через атрибут
data-animation-duration-value="1.5".Stimulus в связке с CSS-анимациями создаёт мощный инструмент для управления динамикой интерфейсов. Контроллеры обеспечивают декларативное подключение поведения к DOM, а CSS отвечает за визуальные эффекты. Такой подход позволяет строить сложные, отзывчивые и легко поддерживаемые анимации без перегрузки JavaScript.