Стили в runtime

Mapbox GL JS позволяет динамически изменять визуальное представление карты без необходимости перезагрузки или пересоздания объекта карты. Работа со стилями в runtime открывает возможности для интерактивного изменения слоев, источников данных и визуальных свойств элементов карты.

Ключевой объект для работы со стилями — это экземпляр map, созданный через new mapboxgl.Map({ ... }). В рантайме можно выполнять следующие операции:

  • Добавление и удаление слоев (layer)
  • Добавление и удаление источников данных (source)
  • Изменение свойств слоев и фильтров
  • Манипуляция видимостью элементов карты
  • Анимация и интерактивное обновление данных

Работа с источниками данных

Источники данных (source) — это фундамент карты. Они могут быть различных типов: geojson, vector, raster, image и др.

Добавление источника:

map.addSource('places', {
    type: 'geojson',
    data: {
        type: 'FeatureCollection',
        features: [
            {
                type: 'Feature',
                geometry: { type: 'Point', coordinates: [30.3158, 59.9398] },
                properties: { name: 'Санкт-Петербург' }
            }
        ]
    }
});

Обновление данных в источнике:

const source = map.getSource('places');
source.setData({
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            geometry: { type: 'Point', coordinates: [37.6173, 55.7558] },
            properties: { name: 'Москва' }
        }
    ]
});

Удаление источника:

map.removeSource('places');

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

Слой (layer) описывает, как данные из источника отображаются на карте. Mapbox GL JS различает типы слоев: symbol, line, fill, circle, raster, hillshade, heatmap.

Добавление слоя:

map.addLayer({
    id: 'places-layer',
    type: 'circle',
    source: 'places',
    paint: {
        'circle-radius': 8,
        'circle-color': '#FF5722',
        'circle-stroke-width': 2,
        'circle-stroke-color': '#FFF'
    }
});

Изменение свойств слоя:

map.setPaintProperty('places-layer', 'circle-color', '#3F51B5');
map.setLayoutProperty('places-layer', 'visibility', 'none'); // скрыть слой
map.setLayoutProperty('places-layer', 'visibility', 'visible'); // показать слой

Удаление слоя:

map.removeLayer('places-layer');

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


Фильтры и условная визуализация

Фильтры позволяют отображать только те объекты, которые соответствуют определённым условиям. Они задаются с помощью массивов, описывающих логику фильтрации.

Пример фильтрации по свойству:

map.setFilter('places-layer', ['==', ['get', 'name'], 'Москва']);

Фильтрация по диапазону значений:

map.setFilter('places-layer', ['all',
    ['>=', ['get', 'population'], 1000000],
    ['<=', ['get', 'population'], 5000000]
]);

Фильтры можно комбинировать через all, any и none.


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

Runtime стили позволяют менять свойства слоя без пересоздания карты. Основные методы:

  • setPaintProperty(layerId, property, value) — изменение визуальных свойств.
  • setLayoutProperty(layerId, property, value) — изменение структурных свойств, таких как расположение или порядок слоев.

Пример динамического изменения цвета и радиуса круга:

map.setPaintProperty('places-layer', 'circle-color', '#4CAF50');
map.setPaintProperty('places-layer', 'circle-radius', 12);

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


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

Слои в Mapbox GL JS отображаются в порядке добавления, но порядок можно изменять в runtime:

map.moveLayer('places-layer', 'roads-layer'); // перемещает слой 'places-layer' над 'roads-layer'

Если второй аргумент не указан, слой перемещается на верхний уровень.


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

Выражения позволяют задавать свойства слоев на основе данных. Они поддерживают условные конструкции, интерполяции, математические и логические операции.

Пример интерполяции цвета по значению свойства:

map.setPaintProperty('places-layer', 'circle-color', [
    'interpolate',
    ['linear'],
    ['get', 'population'],
    100000, '#FFEB3B',
    1000000, '#FFC107',
    5000000, '#F44336'
]);

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


Интерактивные стили через события

Mapbox GL JS позволяет связывать изменения стиля с событиями пользователя:

map.on('mouseenter', 'places-layer', () => {
    map.setPaintProperty('places-layer', 'circle-color', '#FF5722');
});

map.on('mouseleave', 'places-layer', () => {
    map.setPaintProperty('places-layer', 'circle-color', '#3F51B5');
});

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


Практические советы

  • Всегда проверять наличие слоя и источника перед их изменением.
  • Для сложных фильтров и интерполяций использовать выражения (expressions).
  • Для больших наборов данных предпочтительно обновлять GeoJSON источник, а не удалять и добавлять слои заново.
  • Использовать visibility для временного скрытия слоев вместо их удаления, это снижает нагрузку на рендеринг.

Итоговая структура runtime управления стилями

  1. Добавить источник данных через addSource.
  2. Создать слой, указав тип, источник и начальные свойства (addLayer).
  3. Динамически изменять свойства с помощью setPaintProperty и setLayoutProperty.
  4. Фильтровать объекты через setFilter.
  5. Управлять порядком слоев через moveLayer.
  6. Реализовывать интерактивность через события карты.

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