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

В Mapbox GL JS визуализация карты строится вокруг декларативной модели стилей, где каждый визуальный элемент представлен слоем (layer). Слои описывают, как данные из источников (sources) должны отображаться на карте: линии дорог, полигоны зданий, точки интереса, тепловые карты и другие географические сущности.

Слой не содержит геометрии — он лишь интерпретирует данные из источника и задаёт правила отрисовки через параметры paint и layout.


Архитектура слоёв и их связь с источниками

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

  • GeoJSON
  • vector tiles (векторные тайлы)
  • raster tiles
  • image source
  • video source

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

map.addSource('cities', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [69.59, 42.32]
        },
        properties: {
          name: 'City A'
        }
      }
    ]
  }
});

После добавления источника создаётся слой, который использует эти данные.


Основной метод добавления слоя

Для добавления слоя используется метод addLayer:

map.addLayer({
  id: 'cities-layer',
  type: 'circle',
  source: 'cities',
  paint: {
    'circle-radius': 6,
    'circle-color': '#ff5200'
  }
});

Каждый слой обязан иметь:

  • id — уникальный идентификатор слоя
  • type — тип визуализации
  • source — источник данных

Порядок слоёв и стек отрисовки

Слои в Mapbox GL JS образуют стек. Порядок добавления влияет на визуальную приоритетность: более поздние слои отображаются поверх ранних.

Для управления порядком используется второй аргумент addLayer:

map.addLayer({
  id: 'roads',
  type: 'line',
  source: 'transport',
  'source-layer': 'road',
  paint: {
    'line-color': '#333',
    'line-width': 2
  }
}, 'water');

Здесь слой roads будет добавлен перед слоем water.


Основные типы слоёв

fill — полигоны

Используется для отображения площадных объектов: границ, зданий, регионов.

map.addLayer({
  id: 'parks-fill',
  type: 'fill',
  source: 'parks',
  paint: {
    'fill-color': '#00aa55',
    'fill-opacity': 0.4
  }
});

line — линии

Подходит для дорог, маршрутов, границ.

map.addLayer({
  id: 'roads-line',
  type: 'line',
  source: 'roads',
  paint: {
    'line-color': '#888',
    'line-width': 2
  }
});

circle — точки

Используется для отображения точечных объектов.

map.addLayer({
  id: 'cities-circle',
  type: 'circle',
  source: 'cities',
  paint: {
    'circle-radius': 5,
    'circle-color': '#1e90ff'
  }
});

symbol — текст и иконки

Позволяет отображать подписи и маркеры.

map.addLayer({
  id: 'labels',
  type: 'symbol',
  source: 'cities',
  layout: {
    'text-field': ['get', 'name'],
    'text-size': 12
  }
});

fill-extrusion — 3D-экструзии

Используется для построения 3D зданий.

map.addLayer({
  id: 'buildings-3d',
  type: 'fill-extrusion',
  source: 'buildings',
  paint: {
    'fill-extrusion-height': ['get', 'height'],
    'fill-extrusion-color': '#aaa',
    'fill-extrusion-opacity': 0.8
  }
});

heatmap — тепловые карты

Применяется для анализа плотности точек.

map.addLayer({
  id: 'heatmap',
  type: 'heatmap',
  source: 'earthquakes',
  paint: {
    'heatmap-intensity': 1,
    'heatmap-radius': 10
  }
});

Параметры paint и layout

Каждый слой управляется двумя основными группами свойств:

layout

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

  • видимость (visibility)
  • текстовые поля (text-field)
  • иконки (icon-image)
  • размещение текста
layout: {
  visibility: 'visible',
  'text-field': ['get', 'name']
}

paint

Определяет визуальное оформление:

  • цвет
  • прозрачность
  • толщину линий
  • радиус точек
  • высоту экструдирования
paint: {
  'line-color': '#ff0000',
  'line-width': 3
}

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

Слои можно динамически скрывать и отображать через setLayoutProperty:

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

Возврат отображения:

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

Использование фильтров в слоях

Фильтры ограничивают набор отображаемых объектов внутри слоя.

map.addLayer({
  id: 'major-cities',
  type: 'circle',
  source: 'cities',
  filter: ['>', ['get', 'population'], 1000000],
  paint: {
    'circle-color': '#ff0000'
  }
});

Фильтры основаны на выражениях Mapbox Expressions.


Условная стилизация через выражения

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

'circle-color': [
  'interpolate',
  ['linear'],
  ['get', 'population'],
  100000, '#2DC4B2',
  1000000, '#3BB3C3',
  5000000, '#129DD8'
]

Такие конструкции позволяют строить непрерывные шкалы визуализации.


Обновление слоёв

Изменение параметров слоя выполняется без его пересоздания:

map.setPaintProperty('cities-circle', 'circle-radius', 10);

или

map.setFilter('major-cities', ['>', ['get', 'population'], 500000]);

Удаление слоёв

Перед удалением слоя необходимо убедиться, что он не используется другими слоями:

map.removeLayer('cities-circle');

Зависимость порядка слоёв от контекста карты

Слои делятся на логические группы:

  • фоновые (background)
  • водные объекты (water)
  • дороги (road)
  • здания (building)
  • подписи (symbol layers)

Правильное позиционирование слоёв критично для читаемости карты, поскольку неправильный порядок приводит к перекрытию важных объектов менее значимыми.


Слои с источниками vector tiles

При использовании векторных тайлов требуется указание source-layer:

map.addLayer({
  id: 'road-main',
  type: 'line',
  source: 'mapbox-streets',
  'source-layer': 'road',
  paint: {
    'line-color': '#000',
    'line-width': 2
  }
});

source-layer определяет конкретный слой внутри векторного тайлового набора.


Комбинирование нескольких слоёв для одного источника

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

map.addLayer({
  id: 'water-fill',
  type: 'fill',
  source: 'water',
  paint: {
    'fill-color': '#00bfff'
  }
});

map.addLayer({
  id: 'water-outline',
  type: 'line',
  source: 'water',
  paint: {
    'line-color': '#0077aa'
  }
});

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


Динамическое добавление слоёв во время загрузки карты

Слои добавляются только после события load:

map.on('load', () => {
  map.addLayer({
    id: 'cities',
    type: 'circle',
    source: 'cities'
  });
});

Это связано с тем, что стиль карты должен быть полностью инициализирован до модификации.


Взаимодействие слоёв с событиями

Слои участвуют в системе событий:

map.on('click', 'cities-circle', (e) => {
  console.log(e.features);
});

Каждый слой может быть интерактивной областью, если он поддерживает hit-testing.


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

Порядок слоёв влияет не только на визуализацию, но и на обработку событий: верхние слои перехватывают события первыми.