Работа в Svelte

Установка Lottie Web в проект Svelte выполняется стандартно через npm-пакет, после чего становится доступен низкоуровневый API управления анимациями на основе JSON-экспорта из After Effects.

Библиотека подключается как обычный модуль:

npm install lottie-web

После установки становится доступен импорт lottie-web/build/player/lottie_light или полноценный lottie-web, в зависимости от требований к размеру бандла и набору функций.

Базовая структура компонента Svelte

Интеграция строится вокруг DOM-контейнера, в который Lottie рендерит SVG, Canvas или HTML-разметку анимации.

<script>
  import { onMount } from 'svelte';
  import lottie from 'lottie-web';

  let container;
  let animation;
</script>

<div bind:this={container}></div>

Ключевой элемент — привязка bind:this, обеспечивающая доступ к реальному DOM-узлу после монтирования компонента.

Инициализация анимации

Запуск Lottie осуществляется только после появления DOM-элемента, что соответствует жизненному циклу onMount.

<script>
  import { onMount } from 'svelte';
  import lottie from 'lottie-web';
  import animationData from './animation.json';

  let container;
  let animation;

  onMount(() => {
    animation = lottie.loadAnimation({
      container,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData
    });

    return () => {
      animation?.destroy();
    };
  });
</script>

<div bind:this={container}></div>

Экземпляр анимации создаётся один раз и хранится в переменной для последующего управления.

Управление жизненным циклом анимации

Объект, возвращаемый loadAnimation, предоставляет набор методов управления состоянием воспроизведения.

Основные методы управления

  • play() — запуск воспроизведения
  • pause() — приостановка
  • stop() — остановка и сброс к началу
  • destroy() — полное удаление экземпляра
  • setSpeed(value) — изменение скорости воспроизведения
  • goToAndPlay(frame) — переход к кадру с воспроизведением
  • goToAndStop(frame) — переход к кадру с остановкой
animation.pause();
animation.setSpeed(1.5);
animation.play();

Реактивное управление через Svelte-состояние

Svelte позволяет связывать параметры Lottie с реактивными переменными, обеспечивая динамическое изменение поведения анимации.

<script>
  import { onMount } from 'svelte';
  import lottie from 'lottie-web';
  import animationData from './animation.json';

  let container;
  let animation;

  export let speed = 1;
  export let isPlaying = true;

  onMount(() => {
    animation = lottie.loadAnimation({
      container,
      renderer: 'svg',
      loop: true,
      autoplay: false,
      animationData
    });

    return () => animation?.destroy();
  });

  $: if (animation) {
    animation.setSpeed(speed);

    if (isPlaying) {
      animation.play();
    } else {
      animation.pause();
    }
  }
</script>

<div bind:this={container}></div>

Реактивные выражения Svelte обеспечивают синхронизацию состояния анимации с внешними параметрами без ручного контроля обновлений.

Использование Svelte actions

Более инкапсулированный подход реализуется через actions, позволяющие привязать Lottie к любому DOM-элементу декларативно.

// lottieAction.js
import lottie from 'lottie-web';

export function lottieAction(node, params) {
  let animation = lottie.loadAnimation({
    container: node,
    renderer: params.renderer || 'svg',
    loop: params.loop ?? true,
    autoplay: params.autoplay ?? true,
    animationData: params.animationData
  });

  return {
    update(newParams) {
      animation.destroy();
      animation = lottie.loadAnimation({
        container: node,
        ...newParams
      });
    },

    destroy() {
      animation.destroy();
    }
  };
}

Использование в компоненте:

<script>
  import { lottieAction } from './lottieAction.js';
  import animationData from './animation.json';

  let params = {
    renderer: 'svg',
    loop: true,
    autoplay: true,
    animationData
  };
</script>

<div use:lottieAction={params}></div>

Actions позволяют отделить логику управления анимацией от структуры компонента.

Переключение анимаций

Часто требуется динамическая замена JSON-анимации без пересоздания DOM-структуры компонента.

<script>
  import { onMount } from 'svelte';
  import lottie from 'lottie-web';

  import animA from './a.json';
  import animB from './b.json';

  let container;
  let animation;
  let current = animA;

  function load(anim) {
    animation?.destroy();

    animation = lottie.loadAnimation({
      container,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: anim
    });
  }

  onMount(() => {
    load(current);

    return () => animation?.destroy();
  });

  function switchAnim() {
    current = current === animA ? animB : animA;
    load(current);
  }
</script>

<div bind:this={container}></div>

Пересоздание экземпляра является наиболее надёжным способом смены данных анимации.

Работа в SvelteKit и SSR

В средах с серверным рендерингом доступ к window и DOM отсутствует, что требует условной инициализации.

<script>
  import { browser } from '$app/environment';
  import { onMount } from 'svelte';
  import lottie from 'lottie-web';

  let container;

  onMount(() => {
    if (!browser) return;

    const animation = lottie.loadAnimation({
      container,
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: {}
    });

    return () => animation.destroy();
  });
</script>

<div bind:this={container}></div>

Инициализация строго ограничивается клиентской средой.

Управление производительностью

SVG-рендеринг обеспечивает высокое качество, но при сложных анимациях нагрузка на DOM может возрастать.

Применяются следующие подходы:

  • выбор renderer: 'canvas' для тяжёлых сцен
  • отключение autoplay для ленивой загрузки
  • уничтожение экземпляра при размонтировании компонента
  • предотвращение повторной инициализации через проверки состояния
if (animation) return;

События анимации

Lottie предоставляет события жизненного цикла, интегрируемые с Svelte-реактивностью.

animation.addEventListener('complete', () => {
  console.log('анимация завершена');
});

animation.addEventListener('loopComplete', () => {
  console.log('цикл завершён');
});

Обработка событий позволяет синхронизировать анимацию с состоянием интерфейса.

Инкапсуляция через компонентный слой

Часто создаётся специализированный компонент-обёртка, принимающий параметры анимации как props.

<script>
  import { onMount, onDestroy } from 'svelte';
  import lottie from 'lottie-web';

  export let animationData;
  export let loop = true;
  export let autoplay = true;
  export let renderer = 'svg';

  let container;
  let animation;

  onMount(() => {
    animation = lottie.loadAnimation({
      container,
      animationData,
      loop,
      autoplay,
      renderer
    });
  });

  onDestroy(() => {
    animation?.destroy();
  });
</script>

<div bind:this={container}></div>

Такой слой упрощает повторное использование и стандартизирует поведение анимаций в интерфейсе.

Типовые архитектурные паттерны

Использование Lottie в Svelte обычно сводится к нескольким устойчивым моделям:

  • прямое управление через onMount
  • управление через reactive statements
  • инкапсуляция через Svelte actions
  • компонент-обёртка с пропсами
  • динамическая загрузка JSON с внешнего API

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