О чем этот пример
При создании текстовых объектов Phaser по умолчанию вычисляет их визуальные метрики (ascent, descent, fontSize), что требует создания временного Canvas и может снижать производительность, особенно при массовом создании объектов. В этой статье мы разберем, как вручную предоставить эти метрики в конфигурации текста, полностью избежав накладных расходов на их расчет. Этот прием особенно полезен для оптимизации загрузки сцены или создания динамических интерфейсов, где текст генерируется часто.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
// If you provide the Text Metrics in the Text Config then you can
// avoid it having to create a canvas, draw to it, then scan the canvas,
// in order to calculate the metrics internally.
const config1 = {
x: 100,
y: 100,
text: 'Phaser III',
style: {
fontSize: '48px',
fontFamily: 'Arial',
color: '#ffffff',
metrics: {
ascent: 45,
descent: 10,
fontSize: 55
}
}
};
const text = this.make.text(config1);
// You can get the metrics from a Text object by doing this:
console.log(text.getTextMetrics());
console.log(text.toJSON());
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
В чем проблема стандартного подхода?
Когда вы создаете объект текста через this.add.text() или this.make.text(), Phaser для точного позиционирования строки вычисляет её метрики. Этот процесс включает:
1. Создание временного HTMLCanvasElement.
2. Отрисовку на нем текста с заданным стилем.
3. Анализ пикселей холста для определения реальной высоты букв (ascent) и глубины «хвостов» (descent).
Хотя для одного-двух текстовых объектов это незаметно, при создании десятков или сотней элементов (например, в больших таблицах или списках) эти операции могут создать нагрузку, особенно на мобильных устройствах.
// Стандартный способ — Phaser рассчитает метрики сам
const standardText = this.add.text(100, 200, 'Текст', { fontSize: '32px' });
Решение: предоставление метрик вручную
Phaser позволяет указать метрики напрямую в объекте стиля текста, в поле metrics. Это полностью отключает внутренний механизм расчета. Необходимо указать три ключевых свойства:
- ascent: Высота букв над базовой линией (например, у «Т»).
- descent: Глубина букв ниже базовой линии (например, «хвост» у «у»).
- fontSize: Сумма ascent и descent. Обычно немного больше номинального размера шрифта.
Главное правило: значение fontSize в метриках должно быть равно ascent + descent. Визуально это полная высота строки текста.
const configWithMetrics = {
x: 100,
y: 100,
text: 'Phaser III',
style: {
fontSize: '48px', // Номинальный размер для отрисовки
fontFamily: 'Arial',
color: '#ffffff',
metrics: {
ascent: 45, // Высота над линией
descent: 10, // Глубина под линией
fontSize: 55 // ascent + descent (45 + 10)
}
}
};
Как получить точные значения метрик?
Чтобы узнать точные метрики для вашего шрифта и размера, Phaser предоставляет удобный метод.
1. Создайте текстовый объект стандартным способом (хотя бы один раз, например, в момент предзагрузки).
2. Используйте метод .getTextMetrics() этого объекта. Он вернет объект с рассчитанными для данного текста значениями.
3. Скопируйте полученные значения ascent, descent и fontSize в ваш конфиг с метриками для последующего использования.
// 1. Создаем «эталонный» текст
const probeText = this.make.text({ x: 0, y: 0, text: 'Phaser III', style: { fontSize: '48px' } });
// 2. Получаем его метрики
const measuredMetrics = probeText.getTextMetrics();
console.log(measuredMetrics); // Выведет объект с ascent, descent, fontSize
// 3. Уничтожаем пробный объект, если он больше не нужен
probeText.destroy();
Проверка и сериализация
После создания текста с ручными метриками вы можете убедиться, что они корректно применены, и посмотреть на итоговую структуру объекта.
Метод .getTextMetrics() вернет те самые значения, которые вы указали в конфигурации.
Метод .toJSON() сериализует объект текста, включая его стиль и метрики, в JSON-строку. Это полезно для отладки или сохранения состояния.
// Создаем текст с предоставленными метриками
const text = this.make.text(configWithMetrics);
// Проверяем, что метрики установлены верно
console.log(text.getTextMetrics());
// Смотрим на полную JSON-структуру объекта
console.log(text.toJSON());
Что попробовать дальше
Предоставление метрик текста вручную — это простой и эффективный прием оптимизации для сцен с большим количеством текстовых объектов. Он устраняет этап создания и анализа временного Canvas, что ускоряет инициализацию. Для экспериментов попробуйте создать систему кэширования метрик: один раз рассчитайте их для всех используемых в проекте комбинаций шрифта и размера, а затем подставляйте из заранее подготовленного словаря. Также это открывает возможность для точного вертикального выравнивания текста разных размеров без лишних вычислений.
