Atomico — библиотека для создания веб-компонентов с реактивной архитектурой, которая предоставляет удобные инструменты для анимации элементов, в том числе списков. Управление состоянием и реактивность компонентов позволяет реализовать плавные переходы при добавлении, удалении и изменении элементов.
Основной принцип работы с анимацией списков в Atomico — реактивное
отслеживание изменений массива данных. Состояние списка обычно хранится
с помощью функции useState, а при его изменении компоненты
перерендериваются, что позволяет интегрировать анимацию добавления или
удаления элементов.
import { c, useState } from "atomico";
function List() {
const [items, setItems] = useState(["Элемент 1", "Элемент 2"]);
return (
<host>
<ul>
{items.map(item => (
<li>{item}</li>
))}
</ul>
<button onCl ick={() => setItems([...items, `Элемент ${items.length + 1}`])}>
Добавить элемент
</button>
</host>
);
}
customElements.define("animated-list", c(List));
Для анимации используется сочетание CSS-переходов и
реактивных хуков Atomico. Для плавного появления нового
элемента применяют переходы по свойствам opacity и
transform.
li {
transition: opacity 0.3s ease, transform 0.3s ease;
opacity: 0;
transform: translateY(-10px);
}
li.entered {
opacity: 1;
transform: translateY(0);
}
JavaScript-часть отвечает за добавление класса .entered
после монтирования элемента:
import { c, useState, useEffect } from "atomico";
function List() {
const [items, setItems] = useState([]);
const [enteredItems, setEnteredItems] = useState([]);
useEffect(() => {
setEnteredItems(items.map((item, index) => ({ item, id: index })));
}, [items]);
const addItem = () => setItems([...items, `Элемент ${items.length + 1}`]);
return (
<host>
<ul>
{enteredItems.map(({ item, id }) => (
<li key={id} class="entered">{item}</li>
))}
</ul>
<button onCl ick={addItem}>Добавить элемент</button>
</host>
);
}
customElements.define("animated-list", c(List));
Удаление элемента требует двух этапов: сначала анимация исчезновения,
затем удаление из массива. Для этого используют временные состояния и
setTimeout с длительностью CSS-перехода.
function removeItem(index) {
const updated = [...enteredItems];
updated[index].removing = true;
setEnteredItems(updated);
setTimeout(() => {
setItems(items.filter((_, i) => i !== index));
}, 300); // Длительность анимации
}
CSS для удаления:
li.removing {
opacity: 0;
transform: translateY(-10px);
}
Atomico использует реактивные ключи
(key) для отслеживания изменений списка. Это
предотвращает перерендер всех элементов при добавлении или удалении
одного и позволяет оптимизировать анимацию. В примерах выше
key={id} гарантирует правильное сопоставление элементов DOM
с данными массива.
Для более сложных эффектов можно использовать функцию
useAnimationFrame, чтобы управлять анимацией через
JavaScript, создавая последовательное появление элементов или эффекты
“staggered” (поочередное появление).
import { useAnimationFrame } from "atomico";
useAnimationFrame((time) => {
// Реализовать последовательное появление элементов
});
Комбинируя useAnimationFrame с состояниями элементов,
можно создавать эффекты масштабирования, вращения, сдвига и затухания,
которые сложно реализовать чисто через CSS-переходы.
useState для управления массивом
данных.entered) и выхода
(removing).useAnimationFrame или
библиотечные анимации.Такой подход позволяет создавать интерактивные списки с плавными визуальными эффектами, минимизируя количество лишних перерендеров и сохраняя реактивность компонентов Atomico.