Программная генерация JSON-анимаций

Формат Lottie представляет собой декларативное описание анимации в виде JSON-структуры, где каждая анимация строится из набора слоёв, фигур, трансформаций и ключевых кадров. В основе лежит принцип описания сцены как дерева объектов, где каждый элемент имеет собственные параметры и временные зависимости.

Базовые элементы JSON-анимации:

  • layers — список слоёв композиции
  • shapes — геометрические примитивы и их группы
  • ks — ключевые свойства (position, scale, rotation, opacity)
  • ip / op — диапазон кадров (in point / out point)
  • fr — частота кадров
  • w / h — размеры композиции

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

Принцип программной генерации

Программная генерация Lottie-анимаций заключается в создании JSON-структуры динамически, без использования After Effects и Bodymovin как промежуточного инструмента. Такой подход позволяет строить анимации на основе данных, алгоритмов и пользовательских параметров.

Генерация JSON сводится к построению дерева объектов:

  • композиция создаётся как объект верхнего уровня
  • слои добавляются как элементы массива
  • каждый слой содержит набор трансформаций и форм
  • ключевые кадры формируются как массивы значений с временными метками

Основное преимущество подхода — возможность параметризации анимации в реальном времени.

Базовая структура композиции

Минимальная Lottie-композиция может быть описана следующим образом:

const animation = {
  v: "5.7.4",
  fr: 60,
  ip: 0,
  op: 120,
  w: 500,
  h: 500,
  layers: []
};
  • v — версия спецификации
  • fr — частота кадров
  • ip / op — диапазон воспроизведения
  • w, h — размеры сцены

На этом уровне формируется пустая сцена, готовая к наполнению слоями.

Создание слоёв через код

Слой — ключевая единица структуры. Каждый слой описывает объект или группу объектов.

Пример слоя с базовой формой:

const circleLayer = {
  d: 1,
  ty: 4,
  nm: "Circle",
  sr: 1,
  ks: {
    o: { k: 100 },
    r: { k: 0 },
    p: { k: [250, 250, 0] },
    s: { k: [100, 100, 100] }
  },
  shapes: []
};

Здесь:

  • ty: 4 обозначает shape layer
  • ks содержит трансформации
  • p, r, s, o управляют позицией, вращением, масштабом и прозрачностью

Генерация геометрических форм

Фигуры описываются через массив shapes. Каждая форма — объект с типом и параметрами.

Круг

const circleShape = {
  ty: "el",
  p: { k: [0, 0] },
  s: { k: [200, 200] }
};

Прямоугольник

const rectShape = {
  ty: "rc",
  p: { k: [0, 0] },
  s: { k: [300, 150] },
  r: { k: 20 }
};

Обводка

const stroke = {
  ty: "st",
  c: { k: [0, 0.5, 1, 1] },
  w: { k: 4 }
};

Программное управление ключевыми кадрами

Ключевые кадры в Lottie описываются через массив объектов с временными метками.

Базовая структура:

{
  k: [
    { t: 0, s: [0, 0, 0] },
    { t: 60, s: [100, 100, 0] }
  ]
}

Анимация позиции

const positionAnimation = {
  k: [
    { t: 0, s: [100, 100, 0] },
    { t: 30, s: [250, 100, 0] },
    { t: 60, s: [400, 300, 0] }
  ]
};

Анимация прозрачности

const opacityAnimation = {
  k: [
    { t: 0, s: 0 },
    { t: 20, s: 100 },
    { t: 80, s: 100 },
    { t: 120, s: 0 }
  ]
};

Алгоритмическая генерация ключевых кадров

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

Линейная интерполяция

function lerp(a, b, t) {
  return a + (b - a) * t;
}

Используется для построения промежуточных значений:

function generateKeyframes(start, end, frames) {
  const result = [];
  for (let i = 0; i <= frames; i++) {
    const t = i / frames;
    result.push({
      t: i,
      s: [
        lerp(start[0], end[0], t),
        lerp(start[1], end[1], t),
        0
      ]
    });
  }
  return result;
}

Генерация анимаций на основе синусоиды

Использование тригонометрии позволяет создавать органичные движения.

function sineWaveAnimation(amplitude, frequency, frames) {
  const result = [];
  for (let i = 0; i <= frames; i++) {
    const value = Math.sin(i * frequency) * amplitude;
    result.push({
      t: i,
      s: [250 + value, 250, 0]
    });
  }
  return result;
}

Такая генерация используется для:

  • плавных колебаний объектов
  • имитации физических процессов
  • процедурной анимации интерфейсов

Динамическое построение слоёв

Слои могут создаваться на основе массивов данных.

function createBars(count) {
  const layers = [];

  for (let i = 0; i < count; i++) {
    layers.push({
      ty: 4,
      nm: `Bar_${i}`,
      ks: {
        p: { k: [i * 20, 250, 0] },
        s: {
          k: [
            { t: 0, s: [10, 10, 100] },
            { t: 60, s: [10, Math.random() * 200, 100] }
          ]
        }
      },
      shapes: [
        {
          ty: "rc",
          s: { k: [10, 100] }
        },
        {
          ty: "fl",
          c: { k: [0.2, 0.6, 1, 1] }
        }
      ]
    });
  }

  return layers;
}

Такой подход используется для:

  • визуализации данных
  • генерации графиков
  • динамических UI-анимаций

Композиции как результат вычислений

Композиция Lottie может строиться как функция от входных параметров:

function createComposition(width, height, items) {
  return {
    v: "5.7.4",
    fr: 60,
    ip: 0,
    op: 120,
    w: width,
    h: height,
    layers: items
  };
}

Это позволяет создавать масштабируемые анимационные системы.

Генерация переходов между состояниями

Морфинг состояний достигается через интерполяцию наборов параметров.

function transition(from, to, frames) {
  const result = [];

  for (let i = 0; i <= frames; i++) {
    const t = i / frames;

    result.push({
      t: i,
      s: from.map((v, idx) => lerp(v, to[idx], t))
    });
  }

  return result;
}

Используется для:

  • UI переходов
  • анимации графиков
  • трансформации форм

Генерация сложных сцен

Сложные сцены строятся через композицию функций:

  • генерация базовых слоёв
  • наложение эффектов
  • добавление иерархии групп
  • применение временных смещений
const scene = createComposition(800, 600, [
  ...createBars(10),
  circleLayer
]);

Оптимизация структуры JSON

При программной генерации важно учитывать размер и сложность итогового JSON.

Основные подходы оптимизации:

  • минимизация количества ключевых кадров
  • использование повторяющихся ссылок на стили
  • группировка слоёв
  • исключение избыточных свойств

Чем меньше глубина и плотность структуры, тем выше производительность Lottie Web при рендеринге.

Интеграция с Lottie Web

Сгенерированный JSON используется напрямую в библиотеке Lottie Web:

lottie.loadAnimation({
  container: document.getElementById("anim"),
  renderer: "svg",
  loop: true,
  autoplay: true,
  animationData: animation
});

Генерация на стороне кода заменяет статический импорт JSON-файлов, позволяя создавать анимации на лету, без перезагрузки ресурсов.

Параметризация генераторов

Генераторы анимаций становятся универсальными, если вынести параметры:

  • количество элементов
  • диапазон движения
  • скорость
  • амплитуда
  • цветовые схемы
function generateWaveScene({ width, height, density, amplitude }) {
  return createComposition(width, height, sineWaveAnimation(amplitude, 0.1, density));
}

Такая структура превращает анимацию в вычислимую модель, а не статический ресурс.