В экосистеме PixiJS загрузка ресурсов осуществляется
через систему Assets, поддерживающую расширяемую
архитектуру парсеров. Парсер отвечает за преобразование загруженных
данных (JSON, бинарных файлов, изображений и т.д.) во внутренние
структуры, пригодные для использования движком рендеринга.
Стандартные парсеры покрывают большинство сценариев: текстуры, спрайт-листы, шрифты, видео, аудио. Однако при работе со специфическими форматами (кастомные уровни, собственные бинарные структуры, проприетарные форматы анимации) требуется написание собственного парсера.
Парсер интегрируется в пайплайн загрузки и автоматически применяется к файлам подходящего типа.
В версии 7 и выше PixiJS использует модуль Assets,
пришедший на смену устаревшему Loader. Система состоит из
нескольких этапов:
Парсер представляет собой объект со строго определённым интерфейсом:
{
extension: { type, priority },
test(url),
load(url, options),
parse(asset, options, loader)
}
Каждый метод выполняет отдельную задачу.
extensionОписывает тип расширения и приоритет.
extension: {
type: 'load-parser',
priority: 10
}
type — тип расширения (load-parser,
resolve-parser и т.д.)priority — порядок выполнения (чем выше, тем раньше
вызывается)test(url)Определяет, подходит ли парсер для конкретного файла.
test(url)
{
return url.endsWith('.lvl');
}
Метод должен возвращать true, если файл должен быть
обработан этим парсером.
load(url, options)Отвечает за загрузку сырого файла. Можно использовать
fetch:
async load(url)
{
const response = await fetch(url);
return response.arrayBuffer();
}
Метод возвращает данные в “сыром” виде — строку, JSON, ArrayBuffer и т.д.
parse(asset, options, loader)Преобразует загруженные данные в объект, пригодный для использования в приложении.
async parse(asset)
{
const view = new DataView(asset);
const width = view.getUint16(0);
const height = view.getUint16(2);
return {
width,
height
};
}
Возвращаемое значение кешируется и становится результатом
Assets.load().
Парсер необходимо зарегистрировать:
import { extensions } from 'pixi.js';
extensions.add(CustomLevelParser);
После регистрации система автоматически будет применять его к подходящим ресурсам.
Предположим, существует бинарный формат .lvl,
содержащий:
| Смещение | Тип | Описание |
|---|---|---|
| 0 | Uint16 | ширина |
| 2 | Uint16 | высота |
| 4 | Uint8[] | массив тайлов |
const LevelParser = {
extension: {
type: 'load-parser',
priority: 10
},
test(url)
{
return url.endsWith('.lvl');
},
async load(url)
{
const response = await fetch(url);
return response.arrayBuffer();
},
async parse(buffer)
{
const view = new DataView(buffer);
const width = view.getUint16(0, true);
const height = view.getUint16(2, true);
const tiles = new Uint8Array(buffer, 4);
return {
width,
height,
tiles
};
}
};
Регистрация:
extensions.add(LevelParser);
Загрузка:
const level = await Assets.load('level1.lvl');
console.log(level.width);
Если требуется обработка нестандартного JSON:
const CustomJsonParser = {
extension: {
type: 'load-parser',
priority: 10
},
test(url)
{
return url.endsWith('.scene.json');
},
async load(url)
{
const response = await fetch(url);
return response.json();
},
async parse(data)
{
return {
background: data.bg,
objects: data.entities
};
}
};
Такой подход позволяет трансформировать структуру данных под внутренние нужды проекта.
PixiJS выбирает парсер по:
testpriorityЕсли несколько парсеров возвращают true, применяется
тот, у которого выше приоритет.
Это позволяет:
Метод parse может быть асинхронным:
async parse(asset)
{
const texture = await Assets.load(asset.texture);
return {
texture,
meta: asset.meta
};
}
Это позволяет строить сложные зависимости между ресурсами.
Метод parse получает третий аргумент — ссылку на
загрузчик:
async parse(asset, options, loader)
{
const cached = loader.resources.get('sharedData');
return {
asset,
shared: cached
};
}
Это полезно при работе со связанными ресурсами (например, несколько файлов, описывающих один спрайт-лист).
Создание текстуры вручную:
import { Texture, BaseTexture } from 'pixi.js';
async parse(buffer)
{
const blob = new Blob([buffer]);
const imageBitmap = await createImageBitmap(blob);
const baseTexture = BaseTexture.from(imageBitmap);
return new Texture(baseTexture);
}
Парсер может возвращать любой объект, включая:
TextureContainerРезультат parse автоматически сохраняется в кеше
Assets. Повторный вызов Assets.load() вернёт
уже готовый объект.
Удаление из кеша:
Assets.unload('level1.lvl');
Ошибки следует выбрасывать внутри load или
parse:
async parse(asset)
{
if (!asset.signature)
{
throw new Error('Invalid level format');
}
return asset;
}
PixiJS корректно пробросит исключение в вызывающий код.
Возможна обёртка стандартного парсера:
import { spritesheetAsset } from 'pixi.js';
const ExtendedSpritesheetParser = {
...spritesheetAsset,
async parse(asset, options, loader)
{
const sheet = await spritesheetAsset.parse(asset, options, loader);
sheet.customData = asset.meta.customField;
return sheet;
}
};
Регистрация с более высоким приоритетом позволит перехватить стандартное поведение.
При разработке парсера необходимо учитывать:
TypedArrayОсобенно это критично при загрузке больших бинарных файлов или атласов текстур.
PixiJS поддерживает группировку ресурсов:
Assets.addBundle('levels', {
level1: 'level1.lvl',
level2: 'level2.lvl'
});
При загрузке бандла парсер автоматически применяется к каждому ресурсу.
await Assets.loadBundle('levels');
Рекомендуется проверять:
test)Логирование внутри parse упрощает отладку.
Собственные парсеры используются для:
Гибкость архитектуры PixiJS позволяет встроить практически любую систему хранения данных в стандартный пайплайн загрузки, сохраняя единый механизм работы с ресурсами во всём проекте.