Слой типа symbol в Mapbox GL JS предназначен для
отображения текстовых подписей (text) и иконок
(icon). Одной из ключевых задач при работе с такими слоями
является определение места размещения символов относительно геометрии
объекта. За это отвечает свойство
symbol-placement.
Параметр определяет, каким образом подписи и иконки будут располагаться на карте:
От выбора режима зависит внешний вид картографических подписей дорог, рек, маршрутов, границ и других линейных объектов.
Свойство задаётся в блоке layout слоя.
map.addLayer({
id: 'roads-labels',
type: 'symbol',
source: 'roads',
layout: {
'symbol-placement': 'line',
'text-field': ['get', 'name']
}
});
Mapbox GL JS поддерживает три значения:
| Значение | Назначение |
|---|---|
point |
Размещение символов в отдельных точках |
line |
Размещение вдоль всей линии |
line-center |
Размещение в центре линии |
Значение point используется по умолчанию.
layout: {
'symbol-placement': 'point'
}
В этом режиме символ размещается в одной конкретной точке.
Для точечных объектов это естественное поведение:
{
"type": "Point",
"coordinates": [37.6176, 55.7558]
}
Подпись отображается рядом с координатой объекта.
map.addLayer({
id: 'cities',
type: 'symbol',
source: 'cities',
layout: {
'symbol-placement': 'point',
'text-field': ['get', 'city']
}
});
Такой подход применяется для:
Интересно, что режим point может использоваться и для
линий.
Если источник содержит геометрию типа LineString,
система выбирает одну подходящую позицию и размещает подпись как
отдельный объект.
Пример:
layout: {
'symbol-placement': 'point',
'text-field': ['get', 'road_name']
}
Для длинной дороги появится одна подпись вместо множества повторений вдоль маршрута.
Такой вариант подходит, когда необходимо избежать визуальной перегрузки карты.
Значение line предназначено специально для линейных
объектов.
layout: {
'symbol-placement': 'line'
}
В этом режиме текст изгибается вдоль геометрии линии.
Это основной способ подписывания:
map.addLayer({
id: 'road-labels',
type: 'symbol',
source: 'roads',
layout: {
'symbol-placement': 'line',
'text-field': ['get', 'name']
}
});
Если линия имеет изгибы, подпись повторяет её форму.
Например:
─────────────
Main Street
─────────────
или
~~~~~~River~~~~~~
Текст визуально следует за направлением объекта.
Подпись становится частью объекта.
Название реки выглядит как продолжение русла, а название дороги — как элемент дорожной сети.
Не требуется искать свободное место рядом с линией.
Текст располагается непосредственно на объекте.
Пользователь быстрее понимает, к какому объекту относится подпись.
Для корректного размещения требуется достаточная длина линии.
Если объект слишком короткий, подпись может не отображаться.
Например:
{
"type": "LineString",
"coordinates": [
[37.61, 55.75],
[37.62, 55.75]
]
}
Если длина линии меньше длины текста, движок может скрыть подпись.
Это предотвращает наложение символов и ухудшение читаемости карты.
Значение line-center является промежуточным вариантом
между point и line.
layout: {
'symbol-placement': 'line-center'
}
В этом режиме подпись размещается в центре линии, но не изгибается по всей её длине.
Для дороги:
-----------------------
Main Street
-----------------------
Подпись будет находиться примерно посередине геометрии.
При этом текст остаётся единым объектом и не повторяет все изгибы линии.
Режим особенно полезен для:
Пример:
layout: {
'symbol-placement': 'line-center',
'text-field': ['get', 'name']
}
Рассмотрим одну и ту же линию.
Main Street
|
|
|
Подпись существует независимо от геометрии.
Main
Street
Road
Текст повторяет форму линии.
──────────────
Main Street
──────────────
Подпись располагается в центральной части объекта.
Свойство действует не только на текстовые подписи, но и на иконки.
Пример:
layout: {
'symbol-placement': 'line',
'icon-image': 'arrow'
}
Иконки начинают размещаться вдоль линии.
Это часто используется для отображения:
При использовании режима line особое значение
приобретает параметр symbol-spacing.
Он определяет расстояние между повторяющимися символами.
layout: {
'symbol-placement': 'line',
'symbol-spacing': 300
}
Большое значение:
'symbol-spacing': 600
создаёт редкие подписи.
Малое значение:
'symbol-spacing': 100
увеличивает частоту появления символов вдоль линии.
Распространённый сценарий — отображение стрелок вдоль маршрута.
map.addLayer({
id: 'route-arrows',
type: 'symbol',
source: 'route',
layout: {
'symbol-placement': 'line',
'icon-image': 'arrow',
'symbol-spacing': 100
}
});
Результатом становится последовательность стрелок, повторяющих направление движения.
При работе с линиями часто применяется свойство
text-rotation-alignment.
layout: {
'symbol-placement': 'line',
'text-rotation-alignment': 'map'
}
Оно определяет систему координат, относительно которой поворачивается текст.
Наиболее логичным выбором для линейных подписей обычно является режим
map, при котором надпись ориентируется по направлению
объекта.
Для иконок действует аналогичное свойство.
layout: {
'symbol-placement': 'line',
'icon-image': 'arrow',
'icon-rotation-alignment': 'map'
}
Стрелки автоматически следуют форме линии.
Если объект представлен геометрией MultiLineString,
поведение зависит от выбранного режима.
Пример:
{
"type": "MultiLineString",
"coordinates": [
[...],
[...],
[...]
]
}
Создаётся одна позиция для символа.
Каждая часть может получить собственные подписи.
Для каждой линии вычисляется отдельный центр.
При изменении масштаба карты движок постоянно пересчитывает позиции символов.
Для режима line это особенно важно:
Такой механизм обеспечивает читаемость на всех уровнях масштабирования.
Mapbox GL JS использует систему обнаружения пересечений символов.
Даже если задано:
'symbol-placement': 'line'
подпись может не появиться, если рядом уже находится другая надпись.
Для управления этим поведением используются свойства:
'text-allow-overlap'
и
'icon-allow-overlap'
Например:
layout: {
'symbol-placement': 'line',
'text-field': ['get', 'name'],
'text-allow-overlap': true
}
Однако чрезмерное отключение коллизий способно привести к перегруженной карте.
Используется:
'symbol-placement': 'point'
Используется:
'symbol-placement': 'line'
Используется:
'symbol-placement': 'line-center'
Используется комбинация:
{
'symbol-placement': 'line',
'icon-image': 'arrow',
'symbol-spacing': 100
}
Предпочтителен режим:
'symbol-placement': 'line-center'
поскольку чрезмерное искривление текста может ухудшать читаемость.
map.addLayer({
id: 'street-labels',
type: 'symbol',
source: 'streets',
layout: {
'symbol-placement': 'line',
'text-field': ['get', 'name'],
'text-size': 12,
'symbol-spacing': 300,
'text-rotation-alignment': 'map'
},
paint: {
'text-color': '#333333',
'text-halo-color': '#ffffff',
'text-halo-width': 1
}
});
В данном примере названия улиц располагаются непосредственно вдоль дорожной сети, следуют направлению геометрии, автоматически избегают пересечений и масштабируются вместе с картой.