Загрузка кастомных шрифтов

В Mapbox GL JS текстовые подписи на карте формируются через систему glyphs, основанную на растрово-векторных тайлах шрифтов в формате PBF. Вместо привычных TTF/OTF-файлов движок использует заранее сгенерированные наборы глифов, разбитые по диапазонам Unicode. Это обеспечивает быстрый рендеринг текста в WebGL и стабильную производительность при масштабировании и поворотах карты.

Ключевым элементом является свойство стиля:

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

Здесь:

  • fontstack — имя или набор шрифтов, разделённых запятой
  • range — диапазон Unicode-символов (обычно 0–255, 256–511 и т.д.)

Каждый тайл содержит набор символов, необходимых для отображения текста в текущем экстенте карты.


Подсистема text-font и font-stack

Отрисовка текста в слоях управляется свойством text-font, которое принимает массив строк:

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

Каждый элемент массива — это отдельный шрифт. Система работает по принципу fallback: если глиф отсутствует в первом шрифте, он берётся из следующего.

Важно учитывать, что Mapbox GL JS ожидает, что эти шрифты уже существуют в glyphs-источнике, иначе символы будут отображаться как пустые квадраты.


Стандартные шрифты Mapbox

В экосистеме Mapbox используются предустановленные шрифты, доступные через Mapbox Studio и стандартный glyphs endpoint. Наиболее распространённые семейства:

  • Open Sans
  • Roboto
  • Noto Sans
  • DIN
  • Arial Unicode MS (для расширенной Unicode-поддержки)

Эти шрифты оптимизированы под SDF (Signed Distance Field) рендеринг, что позволяет сохранять чёткость при любом масштабе.


Кастомные шрифты через glyphs endpoint

Для использования собственного шрифта необходимо обеспечить генерацию и публикацию glyphs-тайлов.

Структура endpoint выглядит следующим образом:

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

Процесс включает несколько этапов:

  1. Подготовка TTF/OTF файла
  2. Генерация SDF-глифов
  3. Разбиение на диапазоны Unicode
  4. Публикация через HTTP-сервер

Mapbox GL JS будет запрашивать необходимые диапазоны автоматически при рендеринге текста.


Генерация glyph PBF из TTF

Для создания совместимых glyph-тайлов используются специализированные инструменты, такие как fontnik и утилиты на основе node-canvas.

Типичный пайплайн включает:

  • извлечение глифов из TTF
  • преобразование в SDF
  • упаковка в PBF
  • сегментация по Unicode ranges

Пример концептуальной генерации:

TTF → SDF atlas → glyph range (0–255) → PBF tiles

Особое значение имеет корректная настройка диапазонов: слишком крупные диапазоны увеличивают размер запросов, слишком мелкие — количество HTTP-запросов.


Подключение кастомных шрифтов в стиле карты

После публикации glyphs endpoint он указывается в стиле Mapbox GL JS:

const map = new mapboxgl.Map({
  container: "map",
  style: {
    version: 8,
    glyphs: "https://example.com/fonts/{fontstack}/{range}.pbf",
    sources: {
      streets: {
        type: "vector",
        url: "mapbox://mapbox.mapbox-streets-v8"
      }
    },
    layers: [
      {
        id: "labels",
        type: "symbol",
        source: "streets",
        "source-layer": "road",
        layout: {
          "text-field": ["get", "name"],
          "text-font": ["Custom Sans Regular"],
          "text-size": 14
        }
      }
    ]
  }
});

В данном случае движок будет запрашивать:

https://example.com/fonts/Custom%20Sans%20Regular/0-255.pbf
https://example.com/fonts/Custom%20Sans%20Regular/256-511.pbf

SDF-шрифты и особенности рендеринга

Mapbox GL JS использует Signed Distance Field (SDF) для текстовых глифов. Это позволяет:

  • масштабировать текст без потери чёткости
  • применять обводку и тени на GPU
  • использовать одинаковые глифы для разных размеров текста

Однако SDF требует предварительной генерации шрифта. Обычные bitmap fonts не подходят, так как не содержат distance field информации.


Mapbox Studio и управление шрифтами

В экосистеме Mapbox шрифты часто управляются через Mapbox Studio. При загрузке кастомного шрифта:

  • файл автоматически конвертируется в glyphs
  • создаётся набор fontstack-имен
  • публикуется в рамках стиля

Стиль после публикации получает доступ к шрифтам через стандартный mapbox://fonts/ endpoint, без необходимости ручного хостинга.


Фонт-стек и механизм fallback

Font stack — ключевая концепция при работе с многоязычными картами.

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

Принцип работы:

  • сначала ищется глиф в первом шрифте
  • при отсутствии происходит переход к следующему
  • если символ не найден нигде, отображается пустой символ

Это критично при работе с кириллицей, китайским и арабским текстом, где один шрифт редко покрывает весь Unicode диапазон.


Самостоятельный glyph server

При отказе от Mapbox-hosted шрифтов требуется собственный сервер, поддерживающий:

  • CORS-заголовки для браузера
  • корректную маршрутизацию {fontstack}/{range}.pbf
  • кэширование через CDN
  • поддержку HTTP/2 для параллельной загрузки

Рекомендуется использовать CDN-слой, так как количество запросов к glyphs может быть значительным при плотной карте с множеством подписей.


Оптимизация загрузки шрифтов

Производительность системы шрифтов напрямую зависит от структуры glyphs:

  • диапазоны должны быть стандартными (0–255, 256–511)
  • шрифты должны быть заранее подгружены для ключевых языков
  • используется кэш браузера для повторных запросов
  • минимизация font-stack снижает количество fallback-запросов

Дополнительно важно учитывать, что каждый уникальный fontstack увеличивает количество HTTP-запросов при первом рендере слоя.


Частые проблемы при работе с кастомными шрифтами

Отсутствие символов Причина: глифы не включены в диапазон или отсутствуют в SDF генерации.

Разрыв текста (tofu boxes) Причина: несоответствие text-font и доступных glyphs на сервере.

Ошибки загрузки PBF Причина: неверный MIME-type или отсутствие CORS-заголовков.

Несовпадение шрифтов Причина: fontstack в стиле не совпадает с именем, использованным при генерации glyphs.

Низкая производительность Причина: слишком большое количество fontstack или некэшируемые запросы диапазонов.


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

При изменении масштаба карты Mapbox GL JS не перерисовывает весь текст заново, а использует уже загруженные glyph-atlas. Это возможно благодаря:

  • кешированию SDF-глифов
  • повторному использованию текстур в WebGL
  • предзагрузке соседних диапазонов

Это делает систему шрифтов одной из ключевых причин высокой производительности Mapbox GL JS при работе с большим количеством подписей на карте.