Работа с текстом

В Mapbox GL JS отображение текста реализуется через слой типа symbol, в котором текстовые подписи являются частью единой системы символов вместе с иконками. Текст не рендерится как DOM-элементы, а компилируется в GPU-оптимизированные SDF-глифы, поступающие из стилевого источника через glyphs.

Источником текста служат свойства объектов GeoJSON или векторных тайлов. Значения полей извлекаются через выражение text-field, которое формирует строку для отображения.

{
  "id": "cities",
  "type": "symbol",
  "source": "places",
  "layout": {
    "text-field": ["get", "name"]
  }
}

Поле text-field принимает строковые значения и выражения, что позволяет собирать динамические подписи из нескольких атрибутов и литералов.


Источники шрифтов и glyphs

Текст в Mapbox GL JS требует загрузки глифов через параметр glyphs в стиле карты:

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

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

Поддерживаются шрифтовые стеки, например:

layout: {
  "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Regular"]
}

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


Формирование текста через выражения

Mapbox GL JS использует expression system, позволяющую собирать строки без внешней логики.

Конкатенация строк

"text-field": ["concat", ["get", "city"], ", ", ["get", "country"]]

Условная логика

"text-field": [
  "case",
  ["has", "name"],
  ["get", "name"],
  "Unnamed"
]

Обработка отсутствующих значений

"text-field": ["coalesce", ["get", "name"], ["get", "id"]]

Форматирование сложных строк

"text-field": [
  "format",
  ["get", "name"],
  { "font-scale": 1.2 },
  "\n",
  {},
  ["get", "population"],
  { "font-scale": 0.8, "text-color": "#999" }
]

Expression format позволяет смешивать стили внутри одной подписи, задавая различные визуальные параметры для частей текста.


Параметры слоя symbol, влияющие на текст

Размер текста

"text-size": 14

Допускаются также масштабируемые выражения:

"text-size": ["interpolate", ["linear"], ["zoom"], 5, 10, 10, 18]

Размер текста часто связывается с уровнем зума для повышения читаемости.


Смещение текста

"text-offset": [0, 1.5]

Смещение задаётся в единицах em относительно положения геометрии. Первый компонент отвечает за горизонтальное смещение, второй — за вертикальное.


Выравнивание и привязка

"text-anchor": "top"

Доступные значения: center, top, bottom, left, right, а также их комбинации (top-left, bottom-right и т.д.).

Дополнительно управляется выравнивание текста:

"text-justify": "center"

Поворот текста

"text-rotate": 45

Поддерживается как фиксированное значение, так и выражения на основе данных:

"text-rotate": ["get", "bearing"]

Контроль столкновений и плотности подписей

Одной из ключевых систем является collision detection, предотвращающая наложение текста.

Основные параметры

"text-allow-overlap": false
"text-ignore-placement": false
"text-optional": false
  • text-allow-overlap разрешает перекрытие текста
  • text-ignore-placement игнорирует ограничения размещения
  • text-optional делает текст второстепенным по отношению к другим символам

Дополнительно используется:

"text-keep-upright": true

для предотвращения переворачивания текста при вращении карты.


Ограничение длины и переносы

"text-max-width": 8

Задаёт максимальную ширину строки в em. При превышении происходит автоматический перенос.

Также используется:

"text-line-height": 1.2

для управления межстрочным интервалом.


Кейс использования многоязычных данных

При работе с различными языками применяется стратегия fallback через text-font и coalesce:

"text-field": [
  "coalesce",
  ["get", "name:ru"],
  ["get", "name:en"],
  ["get", "name"]
]

Подобный подход обеспечивает корректное отображение локализованных подписей.


Работа с Unicode и RTL-языками

Поддержка Unicode реализуется через соответствующие glyph sets. При использовании арабских или ивритских текстов требуется корректная обработка направления письма, которая выполняется автоматически движком рендеринга.

Особенности:

  • двунаправленный текст обрабатывается на уровне layout engine
  • соединительные формы букв формируются через glyph shaping
  • выбор шрифта критичен для корректного отображения диакритики

Совмещение текста и иконок

Слой symbol объединяет текст и изображения. Иконки задаются через icon-image, а текст — через text-field.

{
  "type": "symbol",
  "layout": {
    "icon-image": "marker",
    "text-field": ["get", "name"],
    "text-offset": [0, 1.2],
    "text-anchor": "top"
  }
}

Порядок отрисовки управляется параметрами:

"icon-text-fit": "none"

или комбинированными режимами размещения.


Динамическое стилизование текста

Mapbox GL JS позволяет изменять визуальные свойства текста в зависимости от данных.

Изменение цвета

"text-color": [
  "case",
  [">", ["get", "population"], 1000000],
  "#ff0000",
  "#333333"
]

Прозрачность

"text-opacity": [
  "interpolate",
  ["linear"],
  ["zoom"],
  5, 0.5,
  10, 1
]

Контур текста

"text-halo-color": "#ffffff",
"text-halo-width": 2

Контур повышает читаемость текста на сложных подложках.


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

Рендеринг текста оптимизируется через SDF (Signed Distance Fields), что позволяет масштабировать шрифты без потери качества.

Ключевые аспекты производительности:

  • уменьшение количества символов в одном слое
  • использование text-optional для второстепенных подписей
  • ограничение text-max-width
  • контроль плотности через minzoom и maxzoom
"minzoom": 5,
"maxzoom": 14

Приоритеты отображения текста

Mapbox GL JS использует систему приоритетов:

"symbol-sort-key": ["get", "rank"]

Чем выше значение сортировки, тем раньше размещается текст при конфликте с другими символами.


Работа с многострочными подписями

Разделение строк осуществляется через \n или expression format:

"text-field": ["concat", ["get", "name"], "\n", ["get", "type"]]

или

"text-field": [
  "format",
  ["get", "name"],
  {},
  "\n",
  {},
  ["get", "type"]
]

Управление видимостью текста

Отображение текста контролируется через фильтры слоя:

"filter": ["has", "name"]

или через zoom-условия:

"layout": {
  "visibility": "visible"
}

В сочетании с minzoom и maxzoom формируется система масштабного появления подписей.


Текстовые стили и визуальная иерархия

Визуальная иерархия достигается комбинацией:

  • размера шрифта
  • толщины гарнитуры
  • контрастности
  • halo
  • приоритетов collision

Пример многоуровневой схемы:

"text-size": [
  "interpolate",
  ["linear"],
  ["zoom"],
  5, 10,
  10, 16,
  15, 22
],
"text-halo-width": 1.5,
"text-halo-color": "#ffffff"

Обработка больших наборов текстовых данных

При большом количестве объектов применяется стратегия упрощения:

  • агрегирование данных на уровне источника
  • кластеризация (для point layers)
  • ограничение отображаемых полей
  • использование cluster в GeoJSON source
source: {
  type: "geojson",
  cluster: true,
  clusterMaxZoom: 10,
  clusterRadius: 50
}

Закрепление текста относительно карты

Параметры привязки к геометрии:

"text-pitch-alignment": "auto"
"text-rotation-alignment": "map"
  • map фиксирует текст относительно карты
  • viewport фиксирует относительно экрана
  • auto выбирает поведение автоматически

Эти настройки особенно важны при наклоне карты.


Особенности рендеринга символов в 3D-режиме

При использовании наклона и вращения карты текст адаптируется к перспективе. Используются дополнительные параметры:

"text-keep-upright": true,
"text-ignore-placement": false

Система предотвращает переворачивание текста и сохраняет читаемость в изометрических сценах.


Управление перекрытием текста и иконок

В symbol layer существует приоритет между icon и text:

"layout": {
  "text-optional": false,
  "icon-optional": true
}

Если ресурсы размещения ограничены, система отдает предпочтение обязательным элементам.


Композиция сложных подписей

Сложные подписи формируются через комбинацию данных, стилей и логики:

"text-field": [
  "format",
  ["get", "name"],
  { "font-scale": 1.3, "text-color": "#000" },
  "\n",
  {},
  ["concat", "Pop: ", ["to-string", ["get", "population"]]],
  { "font-scale": 0.9, "text-color": "#666" }
]

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


Управление плотностью подписей на разных зумах

Зависимость текста от масштаба карты реализуется через:

"layout": {
  "visibility": "visible",
  "text-size": ["step", ["zoom"], 10, 5, 14, 10, 18]
}

Пороговая система step обеспечивает дискретное изменение параметров при переходе между уровнями масштаба.