Svelte
Переходы и анимации
Уведомление, которое возникает рывком и так же резко пропадает, выглядит дёшево. Тост должен плавно выехать и мягко угаснуть. Вручную это значит навесить классы, дождаться окончания CSS-перехода, потом удалить узел - и так в каждом месте. Директива transition: в Svelte делает это сама: элемент анимируется при появлении в DOM и при удалении, причём Svelte ждёт окончания анимации выхода, прежде чем убрать узел. Встроенные fade, fly и slide покрывают большинство случаев одной строкой.
- Тост-уведомление выезжает через fly и плавно исчезает при закрытии
- Модальное окно появляется через fade, фон затемняется тем же приёмом
- Раскрывающийся блок FAQ открывается через slide по высоте
- Список задач: при удалении элемента остальные плавно сдвигаются через animate
- Карточки в галерее перетасовываются с пружинной анимацией из пакета motion
Предварительные знания
- Блоки if и each, по которым элементы появляются и исчезают из DOM
- Базовое понимание CSS-переходов и единиц времени в миллисекундах
- Идея ключа в keyed each для отслеживания конкретных элементов
Директива transition: и встроенные эффекты
Директива transition: навешивается на элемент внутри блока if или each и анимирует его и при появлении, и при исчезновении. Когда условие становится истинным, элемент анимированно входит; когда ложным, Svelte проигрывает анимацию выхода и только потом удаляет узел. Эффекты импортируются из svelte/transition: fade меняет прозрачность, fly сдвигает и затемняет, slide раскрывает по высоте, scale масштабирует.
Первый блок использует fade без параметров - элемент плавно проявляется и так же угасает. Второй передаёт параметры fly в фигурных скобках: смещение по оси y и длительность в миллисекундах. Одна директива описывает обе фазы, и Svelte сам дожидается окончания выхода перед удалением узла.
| Эффект | Что меняет | Частые параметры |
|---|---|---|
| fade | Прозрачность | duration, delay |
| fly | Смещение и прозрачность | x, y, duration |
| slide | Высоту | duration, axis |
| scale | Масштаб и прозрачность | start, duration |
Длительность задаётся в миллисекундах через параметр duration. Параметр delay откладывает старт анимации - удобно, когда несколько элементов должны входить по очереди с нарастающей задержкой.
Что делает директива transition: на элементе внутри блока if?
Раздельные in: и out:
Иногда вход и выход должны выглядеть по-разному: элемент выезжает снизу, а исчезает растворяясь. Для этого вместо transition: используют две отдельные директивы: in: для появления и out: для исчезновения. Каждая принимает свой эффект и свои параметры. transition: - это сокращение для случая, когда вход и выход одинаковы; in: и out: разделяют их.
Здесь in:fly задаёт въезд снизу со смещением по y, а out:fade - растворение при удалении. Эффекты независимы, поэтому появление и исчезновение читаются по-разному. Это даёт более выразительную анимацию там, где симметрия входа и выхода нежелательна.
- transition: один эффект — Вход и выход анимируются одинаково. Сокращённая запись для симметричной анимации
- in: и out: раздельно — Вход и выход задаются отдельными эффектами и параметрами. Для случаев, когда фазы должны различаться
Переходы Svelte по умолчанию проигрываются только при изменении состояния, но не при первой отрисовке страницы. Чтобы элемент анимировался и при начальной загрузке, переходу передают параметр, включающий анимацию на старте.
Когда вместо transition: используют отдельные in: и out:?
animate: и плавные величины из motion
transition анимирует появление и исчезновение, но не перестановку оставшихся элементов. Когда в keyed each меняется порядок - элемент удалили, список отсортировали - соседи должны плавно переехать на новые места. За это отвечает директива animate:, обычно с эффектом flip из svelte/animate. Она работает только в блоке each с ключом, потому что Svelte отслеживает позиции по ключам элементов.
Каждый элемент each имеет ключ item, поэтому Svelte знает, какой узел куда переехал. При перемешивании animate:flip плавно перемещает узлы на новые позиции вместо мгновенного скачка. Без ключа в each такая анимация невозможна - Svelte не смог бы сопоставить старые и новые позиции.
Отдельно стоит пакет motion из экосистемы Svelte. Он даёт пружинные и твин-значения: величина не меняется скачком, а плавно стремится к новой через spring или tween. Это применяют к числам вроде позиции, прогресса или счётчика, когда нужна физически плавная интерполяция, а не дискретная смена значения.
Директива animate: требует ключ в блоке each. Без ключа Svelte не отслеживает конкретные элементы и не может анимировать их перестановку - анимация просто не сработает или будет вести себя непредсказуемо. Ключ должен быть стабильным и уникальным.
Какое условие обязательно для работы директивы animate:?
Связь с другими темами
Анимации работают там, где элементы входят и выходят из DOM:
- Компоненты — Переход навешивается на элемент внутри компонента
- Синтаксис шаблонов — Переходы срабатывают на блоках if и each при появлении и удалении
- Actions — Обе директивы на элементах привязаны к жизни узла в DOM
Итог
- Директива transition: анимирует элемент при появлении и исчезновении из DOM одной директивой
- in: анимирует только вход, out: только выход - когда вход и выход должны отличаться
- Встроенные fade, fly, slide и scale импортируются из svelte/transition и принимают параметры
- animate: анимирует перестановку элементов в keyed each, когда меняется их порядок
- Пакет motion даёт пружинные (Spring) и твин (Tween) значения через классы для плавных переходов величин вроде позиции или прогресса
Связанные уроки
- sv-03-components — Переходы навешиваются на элементы внутри компонента, появляющиеся и исчезающие по условию
- sv-04-template-syntax — Анимации работают с блоками if и keyed each, где элементы входят и выходят из DOM
- sv-15-actions — И переходы, и actions - директивы на элементах, привязанные к появлению узла в DOM