Загрузка шрифтов

Текстовые подписи являются одним из ключевых элементов картографического интерфейса. Названия городов, улиц, районов, рек, объектов инфраструктуры и пользовательские метки отображаются при помощи механизма рендеринга текста, встроенного в MapLibre GL JS.

В отличие от обычных веб-страниц, где текст рисуется браузером через CSS и системные шрифты, MapLibre GL JS отображает надписи внутри WebGL-сцены. По этой причине библиотека использует специальную систему загрузки и подготовки шрифтовых данных.

Основными задачами механизма шрифтов являются:

  • отображение подписей на карте;
  • поддержка различных языков;
  • корректная работа масштабирования;
  • высокая производительность при большом количестве текстовых объектов;
  • единый внешний вид карт на разных устройствах.

Как MapLibre GL JS использует шрифты

В стилях карты текст задаётся через свойство text-font слоя типа symbol.

Пример:

{
    "id": "city-labels",
    "type": "symbol",
    "source": "cities",
    "layout": {
        "text-field": ["get", "name"],
        "text-font": ["Open Sans Regular"],
        "text-size": 14
    }
}

Здесь используется шрифт:

Open Sans Regular

Когда карта должна отобразить подпись, происходит следующий процесс:

  1. MapLibre анализирует слой.
  2. Определяет используемый шрифт.
  3. Загружает необходимые глифы.
  4. Создаёт текстуры символов.
  5. Отрисовывает текст через WebGL.

Что такое глифы

Глифом называется графическое представление конкретного символа.

Например, строка:

MapLibre

содержит символы:

M
a
p
L
i
b
r
e

Для отображения каждого символа необходим соответствующий глиф.

MapLibre не загружает весь шрифт целиком. Вместо этого запрашиваются только нужные наборы символов.

Такой подход существенно уменьшает объём передаваемых данных.


Параметр glyphs в стиле карты

Для получения глифов стиль должен содержать специальный параметр:

{
    "glyphs": "https://example.com/fonts/{fontstack}/{range}.pbf"
}

Переменные:

Переменная Назначение
{fontstack} имя шрифта
{range} диапазон Unicode

Пример итогового запроса:

https://example.com/fonts/Open Sans Regular/0-255.pbf

или

https://example.com/fonts/Open Sans Regular/256-511.pbf

Каждый файл содержит набор символов определённого диапазона Unicode.


Формат PBF

MapLibre использует формат:

Protocol Buffers (PBF)

В файлах PBF хранятся:

  • контуры символов;
  • метрики шрифта;
  • информация о позиционировании;
  • дополнительные параметры рендеринга.

Преимущества формата:

  • компактность;
  • высокая скорость загрузки;
  • быстрое декодирование;
  • хорошая интеграция с векторными тайлами.

Структура загрузки глифов

Допустим, карта содержит подпись:

Москва

Последовательность действий выглядит следующим образом:

Текст
    ↓
Определение символов
    ↓
Определение Unicode-диапазонов
    ↓
Запрос PBF-файлов
    ↓
Создание текстур
    ↓
Отрисовка

Если часть символов уже загружена ранее, повторный запрос не выполняется.


Подключение собственного сервера шрифтов

Многие проекты используют собственный сервер для хранения глифов.

Пример настройки:

const map = new maplibregl.Map({
    container: "map",
    style: {
        version: 8,
        glyphs: "https://cdn.example.com/fonts/{fontstack}/{range}.pbf",
        sources: {},
        layers: []
    }
});

Преимущества собственного сервера:

  • полный контроль над шрифтами;
  • независимость от сторонних сервисов;
  • возможность использовать корпоративные гарнитуры;
  • оптимизация производительности.

Использование нескольких шрифтов

Свойство text-font может содержать массив шрифтов.

Пример:

"text-font": [
    "Noto Sans Regular",
    "Arial Unicode MS Regular"
]

MapLibre будет использовать шрифты в указанном порядке.

Алгоритм работы:

Поиск символа в первом шрифте
        ↓
Найден? → используется
        ↓
Не найден
        ↓
Проверка второго шрифта
        ↓
И так далее

Такой механизм особенно полезен для многоязычных карт.


Работа с Unicode

Современные карты часто содержат:

  • латиницу;
  • кириллицу;
  • арабское письмо;
  • китайские иероглифы;
  • японские символы;
  • корейские символы.

Например:

London
Москва
東京
서울
القاهرة

Не каждый шрифт содержит все необходимые символы.

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


Шрифты для многоязычных карт

Часто применяется следующая конфигурация:

"text-font": [
    "Noto Sans Regular",
    "Arial Unicode MS Regular"
]

Причины популярности такого подхода:

  • большой охват Unicode;
  • поддержка большинства мировых языков;
  • минимальное количество отсутствующих символов.

Выбор гарнитуры для карты

При выборе шрифта необходимо учитывать несколько факторов.

Читаемость

Подписи должны легко читаться при разных масштабах.

Хороший вариант:

Open Sans
Roboto
Noto Sans
Inter

Менее подходящий вариант:

Декоративные шрифты
Рукописные шрифты
Узкие дизайнерские гарнитуры

Размер набора символов

Некоторые шрифты содержат лишь латиницу.

Например:

A-Z
a-z
0-9

Для международных проектов этого недостаточно.


Производительность

Чем больше набор символов, тем:

  • больше объём PBF-файлов;
  • выше расход памяти;
  • дольше первоначальная загрузка.

Необходимо соблюдать баланс между универсальностью и скоростью работы.


Локальное хранение шрифтов

Шрифтовые файлы можно хранить непосредственно в проекте.

Структура каталога:

fonts/
├── Open Sans Regular/
│   ├── 0-255.pbf
│   ├── 256-511.pbf
│   └── ...
└── Noto Sans Regular/
    ├── 0-255.pbf
    ├── 256-511.pbf
    └── ...

Настройка:

glyphs: "/fonts/{fontstack}/{range}.pbf"

Преимущества:

  • отсутствие внешних зависимостей;
  • полный контроль над версиями;
  • работа во внутренних сетях.

Кэширование шрифтов

После загрузки глифы сохраняются в памяти браузера.

Это позволяет:

  • уменьшить количество сетевых запросов;
  • ускорить перемещение по карте;
  • повысить отзывчивость интерфейса.

Типичный сценарий:

Первое открытие карты
        ↓
Загрузка глифов
        ↓
Кэширование
        ↓
Повторное использование

Генерация PBF-шрифтов

Обычный файл:

.ttf

или

.otf

не может использоваться напрямую.

Необходима предварительная генерация PBF-наборов.

Популярный инструмент:

fontnik

Схема подготовки:

TTF
   ↓
Fontnik
   ↓
PBF-глифы
   ↓
Размещение на сервере
   ↓
Подключение через glyphs

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

Многие проекты применяют готовый набор шрифтов OpenMapTiles.

Типичная структура URL:

https://fonts.openmaptiles.org/{fontstack}/{range}.pbf

Такой сервис предоставляет готовые PBF-файлы для популярных гарнитур.

Наиболее распространённые:

  • Open Sans;
  • Noto Sans;
  • Roboto;
  • Klokantech Noto Sans.

Ошибки загрузки шрифтов

Некорректный путь

Ошибка:

404 Not Found

Причина:

glyphs: "/font/{fontstack}/{range}.pbf"

при фактическом расположении:

/fonts/

Отсутствие шрифта

В стиле указан:

"text-font": ["Roboto Regular"]

но на сервере отсутствует каталог:

Roboto Regular

В результате текст может не отображаться.


Проблемы CORS

Если глифы загружаются с другого домена, сервер должен отправлять соответствующие CORS-заголовки.

Пример:

Access-Control-Allow-Origin: *

Без этого браузер может блокировать запросы.


Отсутствие символов

Иногда отображаются квадраты или пустые места вместо текста.

Причина:

Шрифт не содержит нужных символов Unicode.

Особенно часто это возникает при работе с:

  • китайским языком;
  • японским языком;
  • корейским языком;
  • арабским письмом.

Отладка загрузки шрифтов

Проверка обычно выполняется через инструменты разработчика браузера.

Полезно контролировать:

Сетевые запросы

Вкладка:

Network

Проверяются запросы вида:

0-255.pbf
256-511.pbf
512-767.pbf

Ответы сервера

Необходимо убедиться, что сервер возвращает:

200 OK

а не:

404
500
403

Консоль браузера

Типичные сообщения:

Failed to load glyph range

или

Glyph PBF not found

Подобные ошибки помогают быстро определить источник проблемы.


Влияние шрифтов на производительность

На крупных картографических проектах количество подписей может достигать десятков тысяч.

На производительность влияют:

  • число используемых гарнитур;
  • размер Unicode-наборов;
  • количество одновременно отображаемых подписей;
  • объём загружаемых PBF-файлов.

Для оптимизации рекомендуется:

  • использовать минимально необходимое число шрифтов;
  • избегать большого количества альтернативных гарнитур;
  • применять кэширование;
  • хранить глифы на быстром CDN;
  • использовать шрифты с подходящим набором символов вместо чрезмерно больших универсальных коллекций.

Практический пример настройки шрифтов

const map = new maplibregl.Map({
    container: "map",
    style: {
        version: 8,
        glyphs: "https://fonts.example.com/{fontstack}/{range}.pbf",
        sources: {
            cities: {
                type: "geojson",
                data: citiesData
            }
        },
        layers: [
            {
                id: "cities",
                type: "symbol",
                source: "cities",
                layout: {
                    "text-field": ["get", "name"],
                    "text-font": [
                        "Noto Sans Regular",
                        "Arial Unicode MS Regular"
                    ],
                    "text-size": 14
                }
            }
        ]
    }
});

В данной конфигурации:

  • используется собственный сервер глифов;
  • подключены два шрифта;
  • обеспечивается поддержка большого количества языков;
  • подписи автоматически получают необходимые наборы символов через механизм загрузки PBF-глифов MapLibre GL JS.