/lottie-player

Универсальный Lottie-плеер

Primary LanguageJavaScript

Плеер для Lottie-анимаций

Плеер для высокопроизводительного проигрывания Lottie-анимаций на веб-страницах. Использует WASM-версию библиотеки RLottie, которая запускается в отдельном процессе (Web Worker): это позволяет по-минимуму задействовать основной поток браузера.

Установка

Модуль устанавливается как обычный npm-пакет, но сначала необходимо добавить в файл .npmrc проекта (если файла нет — нужно его создать) следующую строчку:

@tamtam-chat:registry=https://npm.pkg.github.com

Для установки используем команду npm install:

npm install @tamtam-chat/lottie-player

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

Для воспроизведения Lottie-анимации делаем следующее:

import { createPlayer } from '@tamtam-chat/lottie-player';

// Создаём или получаем <canvas>-элемент, на котором будет
// воспроизводиться анимация
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);

const player = createPlayer({
    // Элемент, в котором отрисовывать анимацию
    canvas,

    // Lottie-анимация. Это может быть как URL на анимацию, так и сам
    // JSON-файл анимации в виде объекта или строки
    movie: '{...}',

    // Воспроизводить анимацию в цикле
    loop: true,

    // Размер кадра анимации. Если не указано — будет взят
    // из canvas-элемента
    width: 100,
    height: 100
});

setTimeout(() => {
    // Завершение анимации и удаление плеера
    player.dispose();
}, 1000);

Warning Стоит учитывать, что библиотека создаёт отдаёт отдельный Worker-процесс для отрисовки анимаций. Само содержимое воркера находится а отдельном файле worker.js, который подгружается по запросу как только будет создана первая анимация. При бандлинге проекта стоит это учитывать и, при необходимости, импортировать файл как отдельный чанк вашего бандла. Для этого нужно получить ссылку на worker.js и передать её загрузчику до того, как будет создана анимация. Вот как это можно сделать при сборке через Vite:

// Получаем ссылку на файл воркера. Этот же вызов добавит новый чанк в сборку
import workerUrl from '@tamtam-chat/lottie-player/dist/worker?url';
import { createPlayer, updateConfig } from '@tamtam-chat/lottie-player';

// Указываем, откуда грузить воркер
updateConfig({ workerUrl });

// Теперь можно запускать анимации
const player = createPlayer({ ... });

Загрузка воркера с другого хоста

По спецификации ссылка на код воркера должна соответствовать same-origin policy основной страницы. Если код располагается на отдельном хосте, можно обойти это ограничение, предварительно загрузив код как Blob:

import { updateConfig } from '@tamtam-chat/lottie-player';
updateConfig({
    // В качестве workerUrl можно отдать функцию, которая вернёт URL
    // или Promise c URL
    workerUrl: async () => {
        const resp = await fetch('https://static.host.com/worker.js', { mode: 'cors' });
        const blob = await resp.blob();
        return URL.createObjectURL(blob);
    }
});

API плеера

У созданного плеера доступны следующие свойства и методы:

  • paused – воспроизведение плеера на паузе.
  • loop – воспроизводить анимацию в цикле.
  • frame – текущий кадр анимации.
  • totalFrames – всего кадров анимации.
  • play() — запустить воспроизведение анимации.
  • pause() — остановить воспроизведение анимации.
  • toggle() — переключение воспроизведения анимации (play/pause).
  • resize(width, height, dpr?) — поменять размер кадра анимации. Чем меньше размер, тем выше производительность.
  • dispose() — завершить анимацию и удалить плеер.
  • on(event, callback) — подписаться на событие event плеера
  • off(event, callback) — отписаться от события event плеера

События плеера

  • mount — к плееру успешно добавлен воркер и загружена анимация, он готов к воспроизведению. В качестве аргумента коллбэка приходит количество кадров в анимации.
  • play — вызвали метод play, начала воспроизводиться анимация.
  • pause — вызвали метод pause, анимация поставлена на паузу.
  • end — отрисовался последний кадр анимации. В зависимости от значения loop, анимация продолжит воспроизводиться с начала или остановится.
  • rendered — впервые отрисовался кадр анимации после монтирования плеера.
  • resize — у плеера поменялся размер после вызова resize. В качестве аргументов приходит новый размер и DPR.
  • dispose — плеер был удалён.

API модуля

У самого модуля доступны следующие импортируемые методы для управления анимациями:

  • createPlayer(options: PlayerOptions): Player — создаёт новый плеер с указанными опциями.
  • dipsosePlayer(player: Player | HTMLCanvasElement | ID) — универсальный механизм для удаления плеера анимации. Можно передать сам плеер, <canvas>-элемент или ID анимации (об этом ниже).
  • updateConfig(config) — обновление конфига модуля. В основном используется для указания ссылки на файл worker.js, но также можно поменять внутренние параметры создания воркеров.
  • pause() — поставить на паузу воспроизведение всех плееров.
  • play() — запустить воспроизведение всех плееров.

Оптимизация воспроизведения

Часто бывают ситуации, когда нужно воспроизводить одну и ту же анимацию в нескольких местах страницы. Например, в мессенджере несколько человек могут отправить один и тот же стикер. Чтобы в таких случаях не создавать несколько разных роликов, которые будут тратить ресурсы на отрисовку одного и того же содержимого, можно объединить плееры в одну группу с помощью атрибута id.

Если указан атрибут id, для всех плееров с одинаковым атрибутом будет создан только один отрисовщик, который отрисует только один кадр и размножит его на все экземпляры. Причём, можно создавать плееры с разным размером: в этом случае отрисовщик нарисует самый большой кадр и сделает копии нужного размера для всех остальных плееров.

import { createPlayer } from '@tamtam-chat/lottie-player';

// Содежимое JSON-файла с анимацией
const movie = '{...}';
// Группирующий идентификатор
const id = 'my-animation';

const player1 = createAnimation({
    id,
    movie,
    canvas: document.querySelector('canvas.movie1'),
    width: 100,
    height: 100
});

const player2 = createAnimation({
    id,
    movie,
    canvas: document.querySelector('canvas.movie2'),
    width: 200,
    height: 200
});

Из примера выше будет создан только один процесс отрисовки для ролика, будет отрисовываться кадр размером 200×200 как самый большой из группы.