Shared element transitions представляют собой технику анимации, при которой один и тот же элемент визуально перемещается между разными страницами или компонентами, создавая ощущение непрерывного взаимодействия. В SvelteKit это реализуется за счет комбинации реактивности Svelte, системы маршрутизации и CSS-анимаций или библиотек для работы с motion.
Элемент как мост Элемент, который анимируется между состояниями или страницами, должен быть идентифицирован уникальным ключом или атрибутом. Этот ключ позволяет системе понять, что элемент на новой странице — это продолжение того же элемента с предыдущей страницы.
<div bind:this={card} data-shared-id="card-1">
<h2>{title}</h2>
</div>
Здесь data-shared-id="card-1" играет роль
идентификатора, который связывает исходный и целевой элементы.
Состояния и позиции Для корректной анимации
необходимо определить начальное и конечное состояние элемента: размеры,
позицию на экране и стиль. Это можно сделать через реактивные переменные
и методы getBoundingClientRect().
let rectStart, rectEnd;
function captureStart() {
rectStart = card.getBoundingClientRect();
}
function captureEnd() {
rectEnd = card.getBoundingClientRect();
}
Разница между rectStart и rectEnd
используется для расчета анимации трансформации.
Использование animate и
transition Svelte предоставляет встроенные функции
animate:flip и transition, которые позволяют
создавать плавные перемещения и трансформации элементов. Для shared
element transitions чаще всего применяется техника FLIP (First,
Last, Invert, Play).
<div
animate:flip
style="transform-origin: top left;"
bind:this={card}
data-shared-id="card-1"
>
<h2>{title}</h2>
</div>
Алгоритм FLIP состоит из:
Shared element transitions особенно полезны при навигации между
страницами. В SvelteKit маршруты — это файлы в src/routes,
а переходы между ними можно перехватывать через хук
beforeNavigate или afterNavigate.
import { afterNavigate } from '$app/navigation';
afterNavigate(() => {
captureEnd();
animateTransition();
});
Такой подход гарантирует, что элемент будет плавно переходить даже при полной смене DOM.
Некоторые библиотеки UI для SvelteKit уже предоставляют готовые компоненты для shared element transitions. Например:
Svelte Motion Предоставляет реактивные анимации с поддержкой FLIP и drag. Пример использования:
<Motion.div
layoutId="card-1"
transition={{ duration: 0.5, easing: cubicOut }}
>
<h2>{title}</h2>
</Motion.div>
Здесь layoutId выполняет роль идентификатора shared
element.
Svelte-UI Kits Некоторые UI-библиотеки включают
компонент SharedTransition, который оборачивает элемент и
автоматически отслеживает изменения его позиции между страницами или
состояниями.
<SharedTransition id="card-1" duration={400}>
<Card>{title}</Card>
</SharedTransition>
Параметр id связывает элементы на разных страницах, а
duration регулирует длительность анимации.
getBoundingClientRect() для
больших списков.will-change: transform в стилях CSS для
GPU-ускорения.Переход с динамическим контентом Если содержимое
элемента изменяется, необходимо обновлять ключ
(data-shared-id) или layoutId, чтобы анимация
учитывала новый контент.
Комбинирование с маршрутными анимациями Shared element transitions можно совмещать с fade-in/fade-out страниц, создавая эффект, что элементы «переезжают» между экранами, а фон плавно исчезает или появляется.
Сложные трансформации Можно комбинировать перемещение, масштабирование и повороты. Для этого вычисляют матрицы трансформации на основе начальных и конечных координат.
Эта методика позволяет создавать интерфейсы с высоким уровнем визуальной связанности, плавными переходами и ощущением «живости» приложения без использования тяжелых сторонних анимационных фреймворков.