Atomico — библиотека для создания веб-компонентов на основе JavaScript с реактивным подходом. Одним из важных аспектов интерфейсной разработки является управление анимацией при монтировании компонентов. В Atomico это реализуется через сочетание реактивных хуков и API для работы с жизненным циклом компонента.
useEffect для инициализации анимацииДля запуска анимации при появлении компонента используется
стандартный хук useEffect. Основная задача — запустить
анимацию один раз после того, как компонент будет добавлен в DOM.
import { c, useEffect, useRef } from "atomico";
function FadeInComponent() {
const ref = useRef();
useEffect(() => {
const el = ref.current;
if (!el) return;
el.style.opacity = 0;
el.style.transition = "opacity 0.5s ease-in-out";
requestAnimationFrame(() => {
el.style.opacity = 1;
});
}, []);
return <div ref={ref}>Пример анимации при монтировании</div>;
}
customElements.define("fade-in-component", c(FadeInComponent));
Ключевые моменты:
useRef используется для получения
ссылки на DOM-элемент.requestAnimationFrame позволяет
корректно применить CSS-транзишн после добавления элемента в DOM.useEffect.@keyframes и CSS-анимациямиПомимо прямого изменения стилей, Atomico поддерживает интеграцию с
CSS-анимациями через keyframes. Это позволяет более гибко
управлять сложными эффектами без JavaScript.
import { c, css } from "atomico";
const styles = css`
@keyframes fade-in {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
:host {
display: block;
animation: fade-in 0.6s ease forwards;
}
`;
function FadeInAnimation() {
return <div>Анимация через CSS keyframes</div>;
}
FadeInAnimation.styles = styles;
customElements.define("fade-in-animation", c(FadeInAnimation));
Особенности:
:host позволяет применить анимацию ко всему
компоненту.forwards сохраняет
конечное состояние анимации после её завершения.Для компонентов с несколькими элементами, которые должны появляться
поочередно, используется массив ссылок и задержка с
setTimeout или библиотека anime.js.
import { c, useEffect, useRef } from "atomico";
function SequentialFade() {
const refs = useRef([]);
useEffect(() => {
refs.current.forEach((el, i) => {
if (!el) return;
el.style.opacity = 0;
el.style.transition = "opacity 0.4s ease";
setTimeout(() => {
el.style.opacity = 1;
}, i * 200);
});
}, []);
return (
<div>
{["Первый", "Второй", "Третий"].map((text, i) => (
<div key={i} ref={el => (refs.current[i] = el)}>
{text}
</div>
))}
</div>
);
}
customElements.define("sequential-fade", c(SequentialFade));
Особенности подхода:
i * 200 создаёт эффект поочередного
появления.Atomico легко интегрируется с внешними библиотеками анимации, такими как GSAP, anime.js или Framer Motion (через Web Components). Пример с GSAP:
import { c, useEffect, useRef } from "atomico";
import { gsap } from "gsap";
function GsapFade() {
const ref = useRef();
useEffect(() => {
gsap.from(ref.current, { opacity: 0, y: 30, duration: 0.5 });
}, []);
return <div ref={ref}>GSAP-анимация при монтировании</div>;
}
customElements.define("gsap-fade", c(GsapFade));
Преимущества интеграции:
Иногда требуется запуск анимации только при появлении
компонента в DOM в ответ на условие. В Atomico это реализуется
через реактивное свойство и хук useEffect.
import { c, useState, useEffect, useRef } from "atomico";
function ConditionalFade() {
const [show, setShow] = useState(false);
const ref = useRef();
useEffect(() => {
if (show && ref.current) {
ref.current.style.opacity = 0;
ref.current.style.transition = "opacity 0.5s";
requestAnimationFrame(() => {
ref.current.style.opacity = 1;
});
}
}, [show]);
return (
<div>
<button onCl ick={() => setShow(!show)}>Показать/Скрыть</button>
{show && <div ref={ref}>Появляющийся блок</div>}
</div>
);
}
customElements.define("conditional-fade", c(ConditionalFade));
Ключевые моменты:
show управляет условным рендерингом.useState и useEffect позволяет
плавно интегрировать анимацию в логику приложения.useRef, useEffect и тайминговых функций
обеспечивает полный контроль над визуальными эффектами.Эти приёмы позволяют создавать веб-компоненты с плавными и отзывчивыми анимациями без потери производительности и гибкости реактивного подхода.