Layout properties

В Mapbox GL JS свойства слоя делятся на две большие категории:

  • Layout properties — определяют структуру отображения объектов на карте.
  • Paint properties — отвечают за визуальное оформление объектов.

Layout-свойства участвуют в процессе размещения объектов и влияют на то, каким образом данные попадают в сцену рендеринга. При изменении таких параметров движку часто требуется пересчитать расположение элементов слоя, поэтому они считаются более «тяжёлыми» по сравнению с paint-свойствами.

Все layout-свойства задаются внутри объекта layout при создании слоя.

map.addLayer({
    id: 'roads',
    type: 'line',
    source: 'roads-source',

    layout: {
        visibility: 'visible',
        line-cap: 'round',
        line-join: 'round'
    },

    paint: {
        'line-color': '#0066ff',
        'line-width': 4
    }
});

Структура layout

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

{
    id: 'layer-id',
    type: 'symbol',

    layout: {
        // layout properties
    },

    paint: {
        // paint properties
    }
}

Набор доступных layout-свойств зависит от типа слоя:

Тип слоя Layout-свойства
fill visibility, fill-sort-key
line line-cap, line-join, line-sort-key и другие
symbol десятки параметров размещения текста и иконок
circle visibility, circle-sort-key
fill-extrusion visibility
raster visibility
background visibility
heatmap visibility
hillshade visibility

Наиболее сложным и функционально насыщенным является слой типа symbol.


Visibility

Управление отображением слоя

Свойство visibility присутствует практически у всех типов слоёв.

Допустимые значения:

'visible'
'none'

Пример:

layout: {
    visibility: 'none'
}

Такой слой будет полностью скрыт.

Отображение можно изменять динамически:

map.setLayoutProperty(
    'roads',
    'visibility',
    'none'
);

Показ слоя:

map.setLayoutProperty(
    'roads',
    'visibility',
    'visible'
);

Переключение слоёв

Часто используется для создания переключателей интерфейса.

function toggleLayer(layerId) {

    const visibility =
        map.getLayoutProperty(
            layerId,
            'visibility'
        );

    map.setLayoutProperty(
        layerId,
        'visibility',
        visibility === 'visible'
            ? 'none'
            : 'visible'
    );
}

Layout Properties для Line Layers

Линейные слои содержат несколько важных layout-настроек.

type: 'line'

line-cap

Определяет форму окончания линии.

Значения:

'butt'
'round'
'square'

butt

Стандартное обрезанное окончание.

layout: {
    'line-cap': 'butt'
}

round

Скруглённое окончание.

layout: {
    'line-cap': 'round'
}

square

Квадратное окончание.

layout: {
    'line-cap': 'square'
}

Практическое применение

Для дорог чаще всего используется:

layout: {
    'line-cap': 'round'
}

Для инженерных схем и технических чертежей:

layout: {
    'line-cap': 'butt'
}

line-join

Определяет форму соединения сегментов линии.

Допустимые значения:

'bevel'
'round'
'miter'

round

Плавное скругление углов.

layout: {
    'line-join': 'round'
}

Наиболее распространённый вариант для дорог.


bevel

Срезанный угол.

layout: {
    'line-join': 'bevel'
}

miter

Острый угол.

layout: {
    'line-join': 'miter'
}

Часто применяется при построении контуров зданий и технических схем.


line-miter-limit

Ограничивает длину острых соединений типа miter.

layout: {
    'line-join': 'miter',
    'line-miter-limit': 2
}

Большие значения создают длинные выступающие углы.


line-round-limit

Управляет переходом между типами соединений.

layout: {
    'line-round-limit': 1.5
}

Свойство используется редко, но может быть полезно при сложной геометрии.


line-sort-key

Позволяет задавать порядок отрисовки объектов внутри одного слоя.

layout: {
    'line-sort-key': [
        'get',
        'priority'
    ]
}

Если объект имеет большее значение priority, он будет нарисован поверх остальных.

Пример данных:

{
    "priority": 100
}

Layout Properties для Fill Layers

Слои заливки:

type: 'fill'

fill-sort-key

Управляет порядком отображения полигонов.

layout: {
    'fill-sort-key': [
        'get',
        'zIndex'
    ]
}

Полезно при отображении пересекающихся территорий.

Например:

{
    "zIndex": 10
}

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


Layout Properties для Circle Layers

Слои кругов:

type: 'circle'

circle-sort-key

Определяет порядок отрисовки точек.

layout: {
    'circle-sort-key': [
        'get',
        'importance'
    ]
}

Пример:

{
    "importance": 50
}

Более важные объекты отображаются поверх менее важных.


Layout Properties для Symbol Layers

Слой символов является самым сложным типом слоя.

type: 'symbol'

Он отвечает за отображение:

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

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

text-field

Определяет содержимое подписи.

layout: {
    'text-field': ['get', 'name']
}

Если данные содержат:

{
    "name": "Moscow"
}

На карте появится соответствующая подпись.


Форматирование текста

Подстановка нескольких полей:

layout: {
    'text-field': [
        'concat',
        ['get', 'name'],
        ' (',
        ['get', 'population'],
        ')'
    ]
}

Результат:

Moscow (13000000)

text-font

Указывает используемый шрифт.

layout: {
    'text-font': [
        'Open Sans Regular'
    ]
}

Несколько вариантов:

layout: {
    'text-font': [
        'Open Sans Bold',
        'Arial Unicode MS Bold'
    ]
}

text-size

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

layout: {
    'text-size': 16
}

Использование выражений:

layout: {
    'text-size': [
        'interpolate',
        ['linear'],
        ['zoom'],
        5, 10,
        15, 24
    ]
}

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


text-max-width

Максимальная ширина строки.

layout: {
    'text-max-width': 8
}

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


text-letter-spacing

Интервал между символами.

layout: {
    'text-letter-spacing': 0.1
}

Увеличенный интервал:

layout: {
    'text-letter-spacing': 0.4
}

text-line-height

Высота строки.

layout: {
    'text-line-height': 1.4
}

Особенно важно для многострочных подписей.


text-transform

Автоматическое преобразование регистра.

Значения:

'none'
'uppercase'
'lowercase'

Пример:

layout: {
    'text-transform': 'uppercase'
}

Результат:

MOSCOW

Размещение текста

text-anchor

Определяет точку привязки текста.

Возможные значения:

'center'
'left'
'right'
'top'
'bottom'
'top-left'
'top-right'
'bottom-left'
'bottom-right'

Пример:

layout: {
    'text-anchor': 'top'
}

Подпись будет размещаться над объектом.


text-offset

Смещение относительно точки привязки.

layout: {
    'text-offset': [0, 1.5]
}

Подпись будет поднята вверх.


text-radial-offset

Радиальное смещение.

layout: {
    'text-radial-offset': 1.5
}

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


text-justify

Выравнивание текста.

Значения:

'left'
'center'
'right'
'auto'

Пример:

layout: {
    'text-justify': 'center'
}

text-rotation-alignment

Определяет ориентацию текста.

Значения:

'map'
'viewport'
'auto'

map

Текст следует за поворотом карты.

layout: {
    'text-rotation-alignment': 'map'
}

viewport

Текст остаётся горизонтальным относительно экрана.

layout: {
    'text-rotation-alignment': 'viewport'
}

Работа с иконками

icon-image

Указывает изображение символа.

layout: {
    'icon-image': 'airport-icon'
}

Предварительно изображение должно быть добавлено:

map.loadImage('/icons/airport.png', (error, image) => {

    if (error) throw error;

    map.addImage(
        'airport-icon',
        image
    );
});

icon-size

Размер иконки.

layout: {
    'icon-size': 1.2
}

Увеличение:

layout: {
    'icon-size': 2
}

icon-anchor

Точка привязки иконки.

layout: {
    'icon-anchor': 'bottom'
}

Подходит для маркеров, у которых основание должно совпадать с координатой.


icon-offset

Смещение иконки.

layout: {
    'icon-offset': [0, -10]
}

icon-rotate

Поворот изображения.

layout: {
    'icon-rotate': 45
}

Полезно для отображения направления движения.


Управление коллизиями

Одной из ключевых задач Mapbox GL JS является предотвращение наложения подписей.


text-allow-overlap

Разрешает перекрытие текста.

layout: {
    'text-allow-overlap': true
}

По умолчанию движок старается избегать пересечений.


icon-allow-overlap

Разрешает пересечение иконок.

layout: {
    'icon-allow-overlap': true
}

text-ignore-placement

Игнорирует другие подписи.

layout: {
    'text-ignore-placement': true
}

icon-ignore-placement

Игнорирует размещение других иконок.

layout: {
    'icon-ignore-placement': true
}

Практический пример коллизий

Для карты городов:

layout: {
    'text-field': ['get', 'name'],
    'text-size': 14
}

Для критически важных объектов:

layout: {
    'text-field': ['get', 'name'],
    'text-size': 14,
    'text-allow-overlap': true
}

Такие подписи будут отображаться всегда.


Символы вдоль линий

Mapbox GL JS умеет располагать текст непосредственно по геометрии линии.


symbol-placement

Значения:

'point'
'line'
'line-center'

point

Стандартное размещение.

layout: {
    'symbol-placement': 'point'
}

line

Текст следует изгибам линии.

layout: {
    'symbol-placement': 'line'
}

Применяется для названий улиц, рек и маршрутов.


line-center

Подпись располагается в центре линии.

layout: {
    'symbol-placement': 'line-center'
}

symbol-spacing

Интервал между повторяющимися подписями.

layout: {
    'symbol-placement': 'line',
    'symbol-spacing': 250
}

Чем больше значение, тем реже появляются подписи.


Сортировка объектов внутри Symbol Layer

symbol-sort-key

Определяет порядок отображения символов.

layout: {
    'symbol-sort-key': [
        'get',
        'rank'
    ]
}

Пример объекта:

{
    "rank": 100
}

Более высокий ранг получает приоритет при размещении.


Динамическое изменение Layout Properties

Любое layout-свойство можно изменить после создания слоя.

Пример изменения размера текста:

map.setLayoutProperty(
    'cities',
    'text-size',
    20
);

Изменение содержимого подписи:

map.setLayoutProperty(
    'cities',
    'text-field',
    ['get', 'capital']
);

Изменение способа размещения:

map.setLayoutProperty(
    'roads-labels',
    'symbol-placement',
    'line'
);

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

Layout-свойства напрямую влияют на этап размещения объектов.

Наиболее затратными считаются:

  • text-field
  • text-size
  • text-font
  • symbol-placement
  • text-anchor
  • icon-image
  • symbol-sort-key

При изменении таких параметров движок может полностью пересчитать размещение символов слоя.

Для высокопроизводительных приложений рекомендуется:

  • минимизировать частые изменения layout-свойств;
  • использовать выражения вместо постоянных обновлений через JavaScript;
  • объединять связанные изменения в один этап обновления;
  • применять layout только для структурных изменений;
  • использовать paint-свойства для частой анимации и визуальных эффектов.

Именно layout-система обеспечивает интеллектуальное размещение объектов, управление коллизиями, сортировку геометрии и корректное отображение текста и символов на картах любой сложности, являясь одним из ключевых компонентов архитектуры Mapbox GL JS.