Прежде чем вы начнете читать эту статью, пожалуйста, уделите 15 секунд и посетите раздел Что такое Лотти? страница. Это отличная отправная точка для знакомства с Лотти.
Почему нам нужно понимать, что скрывается под капотом?
Лотти повсюду.
В настоящее время доступно множество статей на тему «Лотти». Вы можете изучить их на различных платформах:
* статьи на dev.to
* статьи на Medium
* темы на Reddit
* статьи на hackernoon
Каждый из этих источников дает ценную информацию о том, почему и как использовать Lottie в различных средах.
Многие высоко ценят Лотти по следующим причинам:
* Он имеет небольшой размер файла.
* Он предлагает бесконечную масштабируемость.
* Он поддерживается на различных платформах.
* Анимации, созданные с помощью Lottie, могут быть интерактивными.
Первоначально Lottie был разработан как инструмент для преобразования анимации Adobe After Effects в формат, совместимый с конкретными платформами. Однако он превратился в независимую спецификацию и больше не связан терминологией Adobe After Effects. Вы можете найти спецификацию Лотти.
Недавно LottieFiles представила плагин для Figma, что еще больше расширило популярность и потенциальный рост Lottie. Такое развитие событий означает, что Лотти постепенно становится отраслевым стандартом, что является фантастической новостью для сообщества.
Почти в каждой статье, посвященной «Лотти», подчеркивается ее экосистема и хвалится простота использования. Это действительно простой инструмент, который эффективно выполняет свою задачу. Однако давайте переключим внимание на проблемы, которые могут возникнуть.
Мой личный опыт работы с «Лотти» относится конкретно к веб-разработке, поэтому эти наблюдения могут не иметь отношения к другим средам.
Если вы собираетесь включить анимацию Lottie в веб-проект, официальная документация направит вас на lottie-web.
Сообщество
Давайте посмотрим на список ведущих участников:
- На первом месте с 1602 публикациями находится bodymovin, создатель bodymovin/lottie. Неудивительно, что наибольший вклад внес создатель библиотеки.
- На втором месте с 250 вкладами находится Hernan-dev. Скорее всего, это один и тот же человек.
- На третьем месте с 15 вкладами knekne
который создал полезное вводное [видео об использовании лоттии в Интернете](https://www.youtube.com/watch?v=OSUH81OGuSg)
Из остальных участников было сделано только 80 коммитов, что составляет менее 5% от общего числа коммитов. Большинство этих коммитов могут не иметь прямого отношения к воспроизведению анимации, поиску, применению преобразований или оптимизации отрисовки. Хотя эти коммиты, несомненно, важны, похоже, что основная часть кода в основном поддерживается bodymovin.
Проблемы
С одной стороны, сопровождающие «Лотти» отлично справляются с решением многочисленных проблем. Однако стоит отметить, что наличие 600 открытых вопросов действительно указывает на наличие текущих проблем и областей, требующих внимания. Это говорит о том, что еще предстоит проделать работу для решения этих нерешенных проблем.
Тесты
На момент прекращения моих знаний в мае 2023 года в репозитории GitHub Lottie-web не было доступных тестов. Вполне возможно, что тесты были реализованы во внутренней кодовой базе Airbnb и не были общедоступными. Однако важно отметить, что с тех пор, как вы начали писать эту статью, разработчики добавили [некоторые тесты](https://github.com/airbnb/lottie-web/blob/master/test), что является удачей. совпадение. Это подчеркивает тот факт, что в прошлом участие во внутренних компонентах Лотти было затруднено из-за отсутствия механизмов проверки. Отрадно видеть, что были предприняты шаги для решения этой проблемы путем включения тестов.
Функции
Lottie-web не поддерживает все функции, описанные в формате lottie.
Разные рендереры с разными проблемами
Lottie-web предлагает поддержку рендеринга анимации в контексте холста 2D, SVG и HTML.
Каждый из этих рендереров представляет свой собственный набор проблем. Например, при использовании средства рендеринга холста можно оптимизировать воспроизведение анимации, переместив ее в веб-воркер с помощью [transferControlToOffscreen](https://developer.mozilla.org/en-US/docs/Web/ API/OffscreenCanvas). Это может значительно повысить производительность логики анимации. Однако средство рендеринга SVG не поддерживает эту возможность, поскольку невозможно получить доступ к DOM изнутри веб-работника.
С другой стороны, средство рендеринга SVG предоставляет такие функции, как фильтры размытия с аппаратным ускорением, что делает обновление элементов SVG относительно быстрым. С другой стороны, в средстве рендеринга Canvas отсутствует встроенная поддержка простых фильтров размытия. Кроме того, если SVG содержит множество объектов, это может повлиять на производительность. Поэтому при воспроизведении анимации важно найти баланс между производительностью и желаемыми функциями, принимая во внимание возможности и ограничения каждого средства визуализации.
Вы можете найти разные статьи об этом [например](https://jaredstanley.medium.com/improving-site- Performance-by-optimizing-lottie-animations-9f032972d338)
Или даже [сервис, который оптимизирует вашу лотерею](https://lottiefixer.com/),.
[и это](https://lottiefiles.com/features/optimize-lottie), лол
Действительно, заметно, что многие статьи посвящены оптимизации файлов «Lottie» и их структуры с использованием различных методов. В некоторых случаях такая оптимизация может потребовать внесения изменений в исходный файл After Effects.
› В ближайшее время будут проводиться дополнительные оптимизации, но старайтесь не использовать огромные формы в `AE` только для того, чтобы замаскировать небольшую их часть.
› Слишком большое количество узлов также повлияет на производительность.
Но почему воспроизведение анимации в сети может стать проблемой?…
Для `webgl`, `webgpu` нет средств рендеринга.
Представьте, что вы создаете 2D-игру с использованием WebGL. Было бы здорово включить в вашу игру анимацию, созданную в After Effects. Хотя вы можете рисовать анимацию с помощью элемента холста, ему не хватает некоторых функций. Другой вариант — отображать анимацию в формате SVG, но для ее использования в контексте WebGL вам необходимо сериализовать SVG, преобразовать его в изображение, а затем загрузить это изображение в WebGL. К сожалению, в настоящее время идеального решения для этой проблемы не существует.
На самом деле это не совсем точно. Сама библиотека `lottie-web`
не поддерживает рендеринг в `WebGL`. Однако существует пакет под названием [canvaskit-wasm](https://www.npmjs.com/package/canvaskit-wasm), который обертывает [Skia](https://skia.org) (графический движок) с помощью WebAssembly (wasm). Этот пакет включает модуль под названием [skottie](https://skia.org/docs/user/modules/skottie/), который поддерживает рендеринг анимации в поверхность `WebGL`. Однако у этого подхода есть недостаток: использование wasm требует загрузки относительно большого пакета, и нет уверенности в том, что все функции поддерживаются правильно, как указано в [официальной таблице совместимости](https://github.com/airbnb/ lottie/blob/master/supported-features.md), который отслеживает поддержку lottie на разных платформах, не включает skottie.
История
Я часто задаюсь вопросом, почему эта технология была представлена только в 2015 году. Концепция кажется довольно простой, не правда ли? Ну, возможно, нет. Я предполагаю, что было не так много разработчиков с опытом работы с этим конкретным типом программного обеспечения. Все, что связано с графикой, часто может показаться загадочным царством, почти черной магией, особенно для таких, как я.
Что нам следует делать как сообществу?
Очевидно, что проект «lottie-web» нуждается в помощи.
Как мы можем помочь?
* Пожертвовать Финансовая помощь – один из способов поддержать проект. Даже небольшое ежемесячное пожертвование может изменить ситуацию. Лично я вношу 5 долларов каждый месяц и надеюсь, что [bodymovin](https://github.com/bodymovin) рассмотрит проблемы, которые я открыл, наслаждаясь чашкой кофе, финансируемой моим пожертвованием.
* [contribute](https://github.com/airbnb/lottie-web)
Если у вас есть знания и навыки, прямое участие в проекте — еще один ценный способ помочь. Однако имейте в виду, что внести свой вклад может быть непросто, если вы не знакомы с основами анимации и форматом лотереи. Именно этому и посвящена данная статья!
Демистифицируем «лотти»
Я провел [мастер-класс](https://holyjs.ru/en/talks/8b9ab68b933844869272de89633d0817/?referer=/archive/2023%20Spring/), где попробовал построить лотоплеер с нуля.
[ Еще одно](https://www.youtube.com/watch?v=QAOaBpYLA58&t=1333s) видео может быть вам интересно, речь идет о генерации видео, но в то же время оно пересекается с информацией, которой я собираюсь поделиться .
Наш план:
* Создать простую анимацию в After Effects
* Экспортировать анимацию в json с помощью `bodymovin`
* Изучить содержимое json-файла и его структуру
* Создать демо-версию, в которой мы используем `lottie-web` для рендеринга видео
* Замените `lottie-web` нашим пользовательским рендерером на `webgl`
* Сравните дизайн нашего рендерера с дизайном лоттие-web
Проект в After Effects
Давайте создадим простую анимацию в After Effects.
* Создать проект в After Effects
* Настройка композиции
› Композиция — это основа фильма. Каждая композиция имеет свой таймлайн. Типичная композиция включает в себя несколько слоев, представляющих такие компоненты, как элементы видео- и аудиоматериалов, анимированный текст и векторную графику, неподвижные изображения и освещение.

* Создать сплошной слой
[Здесь](https://helpx.adobe.com/ca/after-effects/using/creating-layers.html) вы можете найти обзор различных слоев, которые вы можете создавать с помощью эффектов After Effects.
Давайте создадим простой слой со сплошным цветом.

Здесь мы можем указать его цвет, ширину и высоту.

Хорошо, это наша анимация:

Но анимации нет!!!
Является ли анимация процессом преобразования чего-либо на экране?
Какие возможности изменения у нас есть?
Когда вы щелкаете по сплошному слою, вы можете заметить, что у него доступна функция «трансформировать».

Вы можете изменить «положение», «поворот», «непрозрачность», «масштаб», «точку привязки» слоя. Давайте кое-что изменим:

На самом деле это нельзя назвать анимацией, поскольку мы меняем только положение начального кадра.
Теперь пришло время ввести «ключевые кадры»:
Давайте переместим наш прямоугольник в правое нижнее положение.

Что это влечет за собой?
Для начального ключевого кадра в момент времени (0) мы указали, что слой должен располагаться в точке (0, 0).
Для второго ключевого кадра в момент времени (2 с) мы заявили свою позицию как (1920, 1080). В течение интервала времени от 0 до 2 секунд положение будет интерполировано с использованием линейной функции.
Теперь, как мы можем создать нелинейную анимацию?
Чтобы добиться этого, мы можем использовать кривые Безье. Эти кривые, названные в честь Пьера Безье, позволяют создавать более сложные и настраиваемые анимации. Вы можете узнать о них больше [здесь](https://en.wikipedia.org/wiki/B%C3%A9zier_curve).
В этом скринкасте мы открыли редактор кривых и выделили кривую для позиции (подробнее мы углубимся в эту тему позже).

Следовательно, у нас есть возможность управлять изменениями координат «x» и «y» с течением времени, используя «кубическую кривую Безье».
Что такое кубический Безье? Подробное объяснение вы можете найти в Википедии, которая предоставляет ценный ресурс по этой теме. Вот [ссылка](https://en.wikipedia.org/wiki/B%C3%A9zier_curve):

Чтобы определить такую кривую, нам нужно указать только две точки, обычно называемые контрольными точками «вход» и «выход».
Например, взгляните на [эту кривую](https://cubic-bezier.com/#0,1,1,0). Она состоит из двух контрольных точек:
* Первая контрольная точка имеет координаты x=0, y=1.
* Вторая контрольная точка имеет координаты x=1, y=0.

Стоит отметить, что мы можем даже создать линейную анимацию, используя кубическую кривую Безье. Просто установите [контрольные точки по диагонали](https://cubic-bezier.com/#.14,.14,.86,.86)

Чтобы упростить нашу первую анимацию, давайте вернемся к линейной анимации.

Хорошо, давайте сохраним нашу анимацию в формате json, для этого мы используем [bodymovin](https://aescripts.com/bodymovin/)
Следуйте [этапам установки плагина](https://github.com/ airbnb/lottie-web#plugin-installation)

Структура Лотти
Давайте посмотрим на сохраненный файл:
```json
{
«v»: «5.10.2»,
«fr»: 29.9700012207031,
«ip»: 0,
«op» : 900.000036657751,
«w»: 1920,
«h»: 1080,
«нм»: «Подвижный квадрат»,
«ddd»: 0,
«активы»: [],
«слои»: [
{
«ddd»: 0,
«ind»: 1,
«ty»: 1 ,
«нм»: «Красное сплошное 1»,
«ср»: 1,
«кс»: {
«о»: {
«а» : 0,
«к»: 100,
«ix»: 11
},
«r»: {
«а»: 0,
«к»: 0,
«ix»: 10
},
«р»: {
«а»: 1,
«к»: [
{
«i»: {
«x»: 0,833,
«y»: 0,833
},
«o»: {
«x»: 0,167,
«y»: 0,167
},
«t»: 0,
«s»: [
0,
0,
0
],
«к»: [
0,
0,
0
],
«ти»: [
0,
0,
0
]
},
{
«t»: 15.0000006109625,< br /> «s»: [
1920,
1080,
0
]
],
«ix»: 2 ,
«л»: 2
},
«а»: {
«а»: 0,
«к»: [
150,
150,
0
],
«ix»: 1,
«л»: 2
},
«s»: {
«a»: 0,
«k»: [
100,
100,
100
],
«ix» : 6,
«л»: 2
},
«ао»: 0,
«ш»: 300,
«ш» : 300,
«sc»: «#ef0c0c»,
«ip»: 0,
«op»: 900.000036657751,
«st»: 0,
«bm»: 0
],
«маркеры»: []
```
Он содержит множество полей с одним-двумя символьными именами. Оно уже застегнуто 😃!
Чтобы понять значение всех полей, мы можем использовать эту [схему лотереи](https://lottiefiles.github.io/lottie-docs/schema/lottie.schema.json)
Еще одна вещь, которую можно удобно [редактор json](https://lottiefiles.github.io/lottie-docs/playground/json_editor/)
На самом деле, у `lottie` очень хорошая [документация](https://lottiefiles .github.io/lottie-docs/concepts/#general-concepts), можете прочитать и пропустить эту статью 😄
Корневой уровень файла «lottie», который в спецификации называется «анимация».
› Объект верхнего уровня, описывающий анимацию
Давайте сосредоточимся на этом
```json
{
«v»: «5.10.2»,
«fr»: 29.9700012207031,
«ip»: 0,
«op» : 900.000036657751,
«w»: 1920,
«h»: 1080,
«нм»: «Подвижный квадрат»,
«ddd»: 0,
«активы»: […],
«слои»: […],
«маркеры»: […]
```
* `v` — версия. Он используется для версионирования данных в соответствии с semver
* `fr` — Частота кадров в секунду
* `ip` — «In Point», с какого кадра начинается анимация (обычно 0)
* `op` — «Точка выхода», в которой кадр анимации останавливается/зацикливается, что определяет продолжительность в кадрах, когда `ip` равен 0
* `w` — Ширина анимации
* `h` — Высота анимации
* `nm` — Имя, как видно из редакторов и т.п.
* `ddd` — Имеет ли анимация 3D-слои
* `layers` — Слои
Итак, я не собираюсь копировать всю спецификацию в эту статью, основная идея, используйте ее, чтобы понять содержание «лотти».
Некоторые схемы поддержки IDE
например, в vscode можно добавить [vscode/settings.json](https://code.visualstudio.com/docs/languages/json)
```json
{
“json.schemas”: [
{
fileMatch: [
src/animations/*.json
],
url: «https://lottiefiles.github.io/lottie -docs/schema/lottie.schema.json'
]
```
И вы получите описание каждого свойства вашего json прямо внутри `IDE`.

С объектом верхнего уровня все ясно.
Что находится внутри [слоев](https://lottiefiles.github.io/lottie-docs/layers/)?
Всего один сплошной слой:
```json
{
«ddd»: 0,
«ind»: 1,
«ty»: 1,
«nm»: «Red Solid 1»,
«ср»: 1,
«ао»: 0,
«ш»: 300,
«ш»: 300,
«сб» : «#ef0c0c»,
«ip»: 0,
«op»: 900.000036657751,
«st»: 0,
«bm»: 0,
«ks»: {
«o»: {
«a»: 0,
«k»: 100,
«ix»: 11
},< br /> «r»: {
«a»: 0,
«k»: 0,
«ix»: 10
},
«p» : {
«a»: 1,
«k»: [
{
«i»: {
«x»: 0,833,
« у»: 0,833
},
«о»: {
«х»: 0,167,
«у»: 0,167
},
«t ”: 0,
«с»: [
0,
0,
0
],
«к»: [
0 ,
0,
0
],
«ти»: [
0,
0,
0
] },
{
«т»: 15.0000006109625,
«с»: [
1920,
1080,
0
]
],
«ix»: 2,
«l»: 2
},
«a»: {
«a»: 0,
«k»: [
150,
150,
0
],
«ix»: 1,
«l»: 2
},
«s»: {
«a»: 0,
«k»: [
100,
100,
100
],
«ix»: 6,
«l»: 2
/> ```
* `ty` — Тип слоя, в нашем случае это 1, что означает сплошной слой по схеме
* `sw` — With
* `sh` — Heigh
* `sc` — цвет, в нашем случае это `#ef0c0c`, который не совсем красный! Хорошо, после эффектов я тебя понял.

Давайте пока пропустим другие свойства и сосредоточимся на важном — `ks`
`ks` — объект Transform, который отвечает за анимацию этого `слоя`.
```json
{
«o»: {
«a»: 0,
«k»: 100,
«ix»: 11
},
«r»: {
«a»: 0,
«k»: 0,
«ix»: 10
},
«р»: {
«а»: 1,
«к»: [
{
«i»: {
«х»: 0,833, «у»: 0,833
},
«о»: {
«х»: 0,167,
«у»: 0,167
},
«т»: 0,
«с»: [
0,
0,
0
],
«до»: [ 0,
0,
0
],
«ти»: [
0,
0,
0
]
},
{
«t»: 15.0000006109625,
«s»: [
1920,
1080,
0
]
],
«ix»: 2,
«l»: 2
},
«a»: {
«а»: 0,
«к»: [
150,
150,
0
],
«ix»: 1,
«л»: 2
},
«с»: {
«а»: 0,
«к»: [
100 ,
100,
100
],
«ix»: 6,
«l»: 2
```
* `o` — непрозрачность
* `r` — поворот
* `p` — положение
* `a` — точка привязки
* `s` — масштаб
Все свойства, которые мы видели в объекте `after Effects`, `transform`.
Каждый из них содержит
Свойство `a`, которое указывает, является ли это свойство анимированным или нет.
Если это не анимированное свойство, это означает, что для него нет `ключевых кадров`, значение статическое.
В нашем примере анимированным свойством является только позиция.
Если свойство не анимировано, `k` содержит статическое значение.
итак, в нашем примере
* `opacity` = 100
* `rotation` = 0
* `anchor point` = [150, 150, 0]
* `scale` = [100, 100, 100]
«position» анимируется, поэтому «k» содержит «ключевые кадры».
```json
[
{
«i»: {
«x»: 0,833,
«y»: 0,833
},
«о»: {
«х»: 0,167,
«у»: 0,167
},
«т»: 0,
«с»: [
0,
0,
0
],
«к»: [
0,
0,
0
],
«ти»: [
0,
0,
0
]
},
{
«t»: 15.0000006109625,
«s»: [
1920,
1080,
0
]
] ```
он описывает 2 ключевых кадра.
для `t` (время) = 0, `s` (состояние/значение) равно [0,0] означает, что наш слой находится в верхнем левом углу сцены
для `t` (время) = 15.000000610962, (состояние /value) равно [1920,1080] означает, что наш слой находится в правом нижнем углу сцены.
Довольно легко, правда?
Это сложнее, чем вы думаете
Первый ключевой кадр содержит другие свойства: `i`, `o`, `to`, `ti`
Что это значит?
Как я упоминал ранее, After Effects поддерживает два разных режима положения.
«разделенный» и «комбинированный» (это не термин «последействия»).
в режиме «разделения» координаты x, y имеют отдельные определения ключевых кадров.
в этом случае у нас будет объект `p` (позиция) следующим образом:
```json
{
«s»: true,
«x»: {
«a»: 1,
«k»: [
],
«ix»: 3
},
«y»: {
«a»: 1,
«k»: [
],
«ix»: 4
```
`s` означает раскол.
давайте рассмотрим `p.x` (position.x)
```json
[
{
«i»: {
«x»: [
0,833
],
«y» : [
0,833
]
},
«о»: {
«х»: [
0,167
],
«у»: [
0,167
]
},
«т»: 0,
«с»: [
0
]
},
{
«t»: 15.0000006109625,
«s»: [
1920
]
]
```
Здесь все просто
для `t` = 0 значение = 0
для `t` = 15.0000006109625, значение = 1920
```json
{
«i»: {
«x»: [
0,833
],
«y»: [
0,833
]
},
«о»: {
«х»: [
0,167
],
«у»: [
0,167
]
```
`i` — означает вход в контрольную точку кубической Безье
`o` — означает выход из контрольной точки кубической Безье
Ранее мы обсуждали значение этих терминов.
Когда используются эти значения, анимация становится линейной.
Теперь давайте вычислим значение FrameNumber = 7. Вот как это можно сделать.
```js
const bezier = new cubicBezier({in: [0.83, 0.83], out = [0.167, 0.167]});
// прогресс между двумя кадрами — это значение от 0 до 1;
const Progress = FrameNumber / (15.0000006109625–0);
const x = bezier.get(progress) * (1920–0);
```
То же самое для `y`.
Обратите внимание, что та же логика интерполяции применима к непрозрачности, повороту, масштабу и т. д.
давайте вернемся к нашему первоначальному случаю с «комбинированной» позицией
Что такое «я», «о», «то», «ти»?
В этом режиме «After Effects» отображает кривую Безье, которая описывает кривую для положения, и это не то же самое, что интерполяционная «кубическая кривая Безье».
В настройках интерполяции `transform.position` мы можем выбрать желаемый тип интерполяции.

Это не меняет способ экспорта в «lottie», потому что, как я упоминал ранее, линия также может быть представлена с помощью кривой Безье.
Давайте рассмотрим этот пример:

В экспортированном `json`
вы можете видеть, что `ti` и `to` описывают входные и выходные контрольные точки двумерного пути Безье.
```json
{
«to»: [
0,
1080,
0
],
«ti»: [
0,
-540, // обратите внимание, что оно относительно значения второго ключевого кадра
0
]
}
```
В этом режиме `ti`, `to` описывают только путь, но как анимационному игроку понять, насколько быстро мы должны перемещать `слой` по этому `пути`?
«Lottie» хранит эту информацию внутри свойств «i» и «o».
В After Effects это можно изменить в настройках скорости ключевого кадра.

Мы рассмотрим интерполяцию положения в этом сценарии позже.
Теперь, когда мы понимаем значение всех ключевых свойств в нашем файле Lottie, мы имеем полное представление об объекте верхнего уровня, хранилище слоев, функциях объекта преобразования и организации ключевых кадров. Мы также знаем, как интерполировать значения, используя эти данные.
Я считаю, что мы готовы создать наш собственный рендерер Lottie с нуля.
Давайте продолжим это в следующей статье.