Изменение цветов элементов

Lottie-анимации строятся на структуре JSON, где каждый визуальный элемент описывается как набор слоёв, фигур и свойств. Цвета в этой структуре не являются «картинкой», они хранятся как числовые значения в объектах fill и stroke, что делает возможным их изменение как на этапе подготовки JSON, так и во время выполнения в браузере через Lottie Web.


Цвет в Lottie задаётся в нормализованном виде — массивом RGB-компонентов от 0 до 1:

"c": {
  "a": 0,
  "k": [1, 0, 0, 1]
}

Где:

  • k — ключевое значение цвета
  • массив [r, g, b, a]
  • каждый компонент находится в диапазоне 0..1

Красный цвет:

[1, 0, 0]

Чёрный:

[0, 0, 0]

Белый:

[1, 1, 1]

Цвета применяются внутри объектов:

  • fl — fill (заливка)
  • st — stroke (обводка)

Пример слоя формы:

{
  "ty": "fl",
  "c": {
    "k": [0.2, 0.6, 1]
  }
}

Получение доступа к анимации через Lottie Web

Lottie Web предоставляет API:

const animation = lottie.loadAnimation({
  container: document.getElementById('app'),
  renderer: 'svg',
  loop: true,
  autoplay: true,
  path: 'animation.json'
});

Ключевой момент: способ изменения цвета зависит от renderer.


Изменение цветов через модификацию JSON до загрузки

Наиболее стабильный и предсказуемый способ — изменение JSON перед передачей в loadAnimation.

fetch('animation.json')
  .then(res => res.json())
  .then(data => {
    data.layers.forEach(layer => {
      traverseShapes(layer);
    });

    lottie.loadAnimation({
      container: document.getElementById('app'),
      renderer: 'svg',
      loop: true,
      autoplay: true,
      animationData: data
    });
  });

Рекурсивный обход структуры:

function traverseShapes(node) {
  if (!node || typeof node !== 'object') return;

  if (node.ty === 'fl' && node.c) {
    node.c.k = [0, 1, 0]; // перекраска в зелёный
  }

  if (node.ty === 'st' && node.c) {
    node.c.k = [1, 0, 0]; // красная обводка
  }

  if (node.it) {
    node.it.forEach(traverseShapes);
  }

  if (node.layers) {
    node.layers.forEach(traverseShapes);
  }
}

Этот метод:

  • не зависит от renderer
  • работает с Canvas и SVG
  • позволяет создавать темы (themes) на уровне данных

Динамическая замена цветов после загрузки (SVG renderer)

При использовании:

renderer: 'svg'

Lottie создаёт DOM-структуру внутри контейнера. Это позволяет напрямую менять fill и stroke.

animation.addEventListener('DOMLoaded', () => {
  const svg = document.querySelector('#app svg');

  const paths = svg.querySelectorAll('path');

  paths.forEach(path => {
    path.setAttribute('fill', '#00ff00');
  });
});

Однако важно понимать ограничение: структура SVG может быть сложной, и не все элементы являются path.

Часто используются:

  • path
  • g
  • circle
  • rect

Более точечный подход:

const groups = svg.querySelectorAll('g');

groups.forEach(group => {
  if (group.getAttribute('data-name') === 'Primary') {
    const shapes = group.querySelectorAll('*');
    shapes.forEach(el => {
      if (el.getAttribute('fill')) {
        el.setAttribute('fill', '#ff0000');
      }
    });
  }
});

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

Lottie позволяет реагировать на кадры:

animation.addEventListener('enterFrame', () => {
  const progress = animation.currentFrame / animation.totalFrames;

  if (progress > 0.5) {
    const svg = document.querySelector('#app svg');
    svg.querySelectorAll('path').forEach(p => {
      p.setAttribute('fill', '#0000ff');
    });
  }
});

Это создаёт эффект изменения палитры в зависимости от времени анимации.


Ограничения изменения цветов в runtime

Lottie Web не предоставляет полноценного API для изменения свойств слоёв на уровне композиции. Поэтому важно учитывать:

  • нет прямого setColor() для shape layers
  • изменения через DOM работают только для SVG renderer
  • Canvas renderer не даёт доступа к отдельным элементам
  • изменения JSON после старта не влияют на уже загруженную анимацию

Использование масок цветов через CSS (SVG renderer)

Для глобального изменения цветовой схемы можно использовать CSS-фильтры:

#app svg {
  filter: hue-rotate(90deg) saturate(1.2);
}

Этот метод:

  • не требует доступа к структуре Lottie
  • работает мгновенно
  • но не даёт точного контроля над конкретными элементами

Перекраска через идентификаторы слоёв (bodymovin naming)

При экспорте из After Effects через Bodymovin можно задавать имена слоёв:

  • PrimaryColor
  • Accent
  • Background

В JSON они попадают как:

"nm": "PrimaryColor"

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

function findLayersByName(data, name) {
  const result = [];

  function walk(node) {
    if (node.nm === name) result.push(node);

    if (node.layers) node.layers.forEach(walk);
    if (node.it) node.it.forEach(walk);
  }

  walk(data);
  return result;
}

И менять цвет выборочно:

const targets = findLayersByName(animationData, 'PrimaryColor');

targets.forEach(layer => {
  traverseShapes(layer);
});

Замена цветов через palette mapping

Подход с палитрой используется для унификации темы:

const palette = {
  primary: [0.1, 0.4, 1],
  secondary: [1, 0.5, 0],
  background: [0.05, 0.05, 0.05]
};

Применение:

function applyPalette(node, palette) {
  if (!node) return;

  if (node.ty === 'fl') {
    node.c.k = palette.primary;
  }

  if (node.ty === 'st') {
    node.c.k = palette.secondary;
  }

  if (node.it) {
    node.it.forEach(n => applyPalette(n, palette));
  }
}

Такой подход удобен для:

  • светлой/тёмной темы
  • брендированных анимаций
  • пользовательских кастомизаций интерфейса

Комбинированные стратегии изменения цветов

В реальных проектах используется гибридный подход:

  1. JSON модификация до загрузки — основной контроль
  2. SVG DOM правки — точечная динамика
  3. CSS фильтры — быстрые эффекты
  4. Семантические имена слоёв — структурная поддержка тем

Пример архитектуры:

const animationData = await loadJSON();

applyPalette(animationData, themePalette);

const anim = lottie.loadAnimation({
  container: el,
  renderer: 'svg',
  animationData
});

anim.addEventListener('DOMLoaded', () => {
  highlightAccentLayers(el);
});

Особенности работы с градиентами

Цвета могут быть не только fl и st, но и градиентами:

"ty": "gf"

Градиенты содержат массив цветов:

"g": {
  "k": {
    "k": [0, 0, 1, 1, 0, 1, 0, 1]
  }
}

Где пары значений — это RGB + позиция.

Изменение требует перерасчёта всего массива:

function replaceGradient(node, from, to) {
  if (node.ty === 'gf' && node.g?.k?.k) {
    node.g.k.k = node.g.k.k.map(v => v === from ? to : v);
  }

  if (node.it) {
    node.it.forEach(n => replaceGradient(n, from, to));
  }
}

Итоговая логика работы с цветами в Lottie Web

Изменение цветов в Lottie Web всегда сводится к работе с одним из трёх уровней:

  • JSON-уровень — полный контроль структуры
  • DOM SVG-уровень — пострендерная модификация
  • CSS-уровень — визуальные эффекты без доступа к данным

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