Page transitions в SvelteKit

SvelteKit предоставляет мощный механизм для реализации переходов между страницами, позволяя создавать плавные и отзывчивые интерфейсы. В отличие от классических SPA-фреймворков, здесь переходы интегрированы с маршрутизацией на уровне файловой структуры src/routes, что упрощает их управление и кастомизацию.

Основной инструмент для реализации переходов — это Svelte transitions (transition, animate и motion), которые применяются к компонентам страниц при их монтировании и размонтировании.

<script>
  import { fade } from 'svelte/transition';
</script>

<div transition:fade>
  Содержимое страницы
</div>

При таком подходе элемент плавно появляется и исчезает при навигации. Для переходов между страницами можно использовать аналогичные механизмы, но с учётом маршрутизации SvelteKit.


Интеграция переходов с маршрутизацией SvelteKit

SvelteKit строится на основе файловой маршрутизации. Каждая страница — это отдельный .svelte файл в src/routes. Чтобы добавить переходы, можно обернуть содержимое страницы в компонент с переходом:

<script>
  import { fly } from 'svelte/transition';
</script>

<main transition:fly="{{ x: 300, duration: 400 }}">
  <slot />
</main>

fly позволяет задать смещение (x и y) и длительность анимации (duration). Переход срабатывает при монтировании страницы, а при уходе со страницы — происходит обратная анимация.

Для глобального контроля переходов можно использовать layout файлы, например src/routes/+layout.svelte, чтобы единообразно применять анимации ко всем страницам:

<script>
  import { fade } from 'svelte/transition';
</script>

<slot transition:fade={{ duration: 300 }} />

Это гарантирует, что каждая страница будет плавно появляться и исчезать при навигации.


Настройка анимаций для навигации

SvelteKit предоставляет события жизненного цикла маршрутов:

  • beforeNavigate — вызывается перед сменой страницы.
  • afterNavigate — вызывается после смены страницы.

Использование этих событий позволяет точно синхронизировать переходы и, при необходимости, запускать дополнительные эффекты:

<script>
  import { beforeNavigate, afterNavigate } from '$app/navigation';
  import { tweened } from 'svelte/motion';
  import { cubicOut } from 'svelte/easing';

  let progress = tweened(0, { duration: 400, easing: cubicOut });

  beforeNavigate(() => {
    progress.set(0);
    progress.set(100);
  });

  afterNavigate(() => {
    progress.set(0);
  });
</script>

<div class="progress-bar" style="width: {progress}%"></div>

Такой подход полезен для индикаторов загрузки и более сложных визуальных эффектов при смене маршрутов.


Комбинирование переходов с состоянием страницы

Для комплексных интерфейсов важно учитывать состояние страницы. Если на странице присутствует динамическое содержимое (например, данные из API), переходы должны корректно обрабатывать появление контента.

<script>
  import { fade, slide } from 'svelte/transition';
  import { onMount } from 'svelte';

  let items = [];

  onMount(async () => {
    const res = await fetch('/api/items');
    items = await res.json();
  });
</script>

{#each items as item (item.id)}
  <div transition:slide>
    {item.name}
  </div>
{/each}

{#each} с ключами (item.id) гарантирует, что каждый элемент будет анимирован индивидуально при рендеринге и обновлении списка.


Продвинутые техники: Page Out/In Transitions

Для более сложных эффектов можно использовать двухфазные переходы: выход со старой страницы и вход новой. Это требует управления двойной отрисовкой в layout:

<script>
  import { fade } from 'svelte/transition';
  import { tick } from 'svelte';

  let currentPage;
  let nextPage;

  export let segment;

  $: if (segment) {
    nextPage = segment;
    handleTransition();
  }

  async function handleTransition() {
    await tick(); // ожидание отрисовки
    currentPage = nextPage;
  }
</script>

{#if currentPage}
  <svelte:component this={currentPage} transition:fade={{ duration: 400 }} />
{/if}

Такой подход позволяет реализовать плавный эффект смены страниц, аналогичный анимациям в мобильных приложениях.


Использование библиотек UI для SvelteKit

Помимо встроенных transition и animate, доступны сторонние UI-библиотеки для SvelteKit, предоставляющие готовые анимации и компоненты переходов:

  • Svelte Motion — расширенные возможности для анимации элементов и страниц.
  • Svelte Transitions UI — коллекция готовых эффектов перехода.
  • Motion One + SvelteKit — высокопроизводительные Web Animations API анимации.

Пример с Motion One:

<script>
  import { animate } from 'motion';

  let container;

  $: if (container) {
    animate(container, { opacity: [0, 1], transform: ['translateY(20px)', 'translateY(0)'] }, { duration: 0.5 });
  }
</script>

<div bind:this={container}>
  Контент с Motion One
</div>

Комбинирование этих библиотек с маршрутизацией SvelteKit позволяет создавать сложные, отзывчивые анимации страниц, при этом сохраняя производительность.


Лучшая практика для Page Transitions

  • Использовать layout компоненты для единообразных эффектов.
  • Применять ключи в {#each} для корректной анимации списков.
  • Синхронизировать переходы с событиями beforeNavigate и afterNavigate.
  • Для сложных интерфейсов использовать двухфазные переходы: exit + enter.
  • Рассматривать сторонние библиотеки для готовых анимаций и улучшенной производительности.

Такой подход обеспечивает гибкость и масштабируемость при разработке интерфейсов с плавной сменой страниц в SvelteKit.