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

Слои в Mapbox GL JS являются ключевым механизмом визуализации геоданных. Именно слои определяют, как данные из источников (sources) отображаются на карте: в виде линий, полигонов, точек, растровых тайлов или 3D-объектов. Архитектура слоёв строится вокруг декларативного описания стиля, где каждый слой представляет собой независимую единицу рендеринга с собственными параметрами отображения и правилами фильтрации данных.

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

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

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

symbol — текстовые и иконографические маркеры. Используется для POI, подписей, меток.

circle — точечные данные в виде окружностей. Часто применяется для кластеризации или визуализации плотности.

raster — растровые тайлы, например спутниковые снимки.

fill-extrusion — 3D-экструзия полигонов. Используется для визуализации зданий.

heatmap — тепловые карты плотности данных.

hillshade — визуализация рельефа.

Каждый тип слоя имеет собственный набор свойств в секциях layout и paint, что определяет поведение слоя на уровне геометрии и визуального оформления.

Добавление слоёв в карту

Основной способ создания слоя — метод addLayer.

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

Каждый слой обязан иметь уникальный id. Параметр source указывает на источник данных, который должен быть заранее добавлен через addSource. Векторные тайлы требуют указания source-layer, определяющего конкретный слой внутри тайлового набора.

Порядок добавления влияет на порядок отрисовки: последние добавленные слои отображаются выше предыдущих.

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

Порядок слоёв определяет визуальную иерархию. Mapbox GL JS использует стековую модель рендеринга: каждый новый слой добавляется поверх существующих.

Добавление слоя перед другим слоем

map.addLayer({
  id: 'water-outline',
  type: 'line',
  source: 'water',
  paint: {
    'line-color': '#0000ff'
  }
}, 'road-label');

Второй аргумент addLayer задаёт beforeId, то есть слой, перед которым будет вставлен новый.

Перемещение слоя

map.moveLayer('roads', 'water');

Метод moveLayer изменяет порядок существующего слоя, перемещая его выше или ниже указанного слоя.

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

Получение информации о слое

const layer = map.getLayer('roads');

Метод возвращает объект описания слоя, включая его тип, источник и стили.

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

Видимость слоя управляется через layout.visibility.

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

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

  • visible — слой отображается
  • none — слой скрыт

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

Изменение визуальных свойств слоя

Слои разделяют свойства на две категории: layout и paint.

  • layout — структурные параметры (видимость, символы, размещение текста)
  • paint — визуальные параметры (цвет, прозрачность, ширина линий)

Изменение paint-свойств

map.setPaintProperty('roads', 'line-color', '#00ff00');
map.setPaintProperty('roads', 'line-width', 4);

Изменение layout-свойств

map.setLayoutProperty('roads', 'line-cap', 'round');

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

Фильтрация данных слоя

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

map.setFilter('roads', ['==', 'type', 'highway']);

Фильтры используют выражения Mapbox Expression API и поддерживают логические операции:

map.setFilter('roads', [
  'all',
  ['==', 'type', 'highway'],
  ['>=', 'lanes', 2]
]);

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

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

map.removeLayer('roads');

Удаление слоя не затрагивает источник данных. Один источник может использоваться несколькими слоями одновременно.

Взаимодействие слоёв с источниками данных

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

  • vector
  • raster
  • geojson
  • image
  • video

Пример GeoJSON-источника:

map.addSource('points', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: []
  }
});

Слой, использующий этот источник:

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

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

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

map.addLayer({
  id: 'population',
  type: 'circle',
  source: 'cities',
  paint: {
    'circle-radius': [
      'interpolate',
      ['linear'],
      ['get', 'population'],
      1000, 4,
      1000000, 20
    ],
    'circle-color': [
      'step',
      ['get', 'population'],
      '#00ff00',
      100000,
      '#ffff00',
      500000,
      '#ff0000'
    ]
  }
});

Выражения позволяют строить сложные визуальные правила без внешней логики JavaScript.

Управление прозрачностью слоёв

Прозрачность регулируется через свойства paint:

map.setPaintProperty('water', 'fill-opacity', 0.5);

Для линий:

map.setPaintProperty('roads', 'line-opacity', 0.3);

Для символов:

map.setPaintProperty('labels', 'text-opacity', 0.8);

Слои символов и управление конфликтами

Слой symbol обладает механизмом разрешения конфликтов подписи. Он управляет пересечением текста и иконок.

map.addLayer({
  id: 'labels',
  type: 'symbol',
  source: 'places',
  layout: {
    'text-field': ['get', 'name'],
    'text-size': 12,
    'text-allow-overlap': false,
    'text-ignore-placement': false
  }
});

Ключевые параметры:

  • text-allow-overlap — разрешение наложения текста
  • icon-allow-overlap — разрешение наложения иконок
  • symbol-sort-key — приоритет отображения

Динамическое управление слоями в реальном времени

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

function highlightRoads(enabled) {
  map.setPaintProperty(
    'roads',
    'line-color',
    enabled ? '#ff0000' : '#888888'
  );
}

Изменения применяются мгновенно благодаря WebGL-рендереру.

Работа с несколькими слоями одного источника

Один источник может быть использован несколькими слоями для создания сложных эффектов.

map.addLayer({
  id: 'road-base',
  type: 'line',
  source: 'roads',
  paint: {
    'line-color': '#333',
    'line-width': 6
  }
});

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

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

Приоритет слоёв и z-index логика

В отличие от CSS, Mapbox GL JS не использует явный z-index. Порядок определяется положением слоя в стиле.

Стек слоёв можно рассматривать как массив:

  • нижние слои — фоновые данные (водоёмы, земля)
  • средние слои — геометрия (дороги, здания)
  • верхние слои — подписи и интерактивные элементы

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

Состояния слоя и производительность

Слои рендерятся через WebGL, поэтому изменения свойств проходят через GPU-пайплайн. Частое обновление свойств:

  • предпочтительнее выполнять через setPaintProperty
  • избегать пересоздания слоёв
  • минимизировать сложные фильтры на больших наборах данных

Использование выражений вместо JavaScript-логики снижает нагрузку на основной поток.

Интерактивность слоёв

Слои участвуют в событиях карты:

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

Hover-состояния:

map.on('mousemove', 'roads', (e) => {
  map.setPaintProperty('roads', 'line-color', '#ff9900');
});

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

Использование фильтров для интерактивного управления

Фильтры часто применяются для подсветки объектов:

map.setFilter('roads', [
  '!=',
  ['get', 'id'],
  selectedId
]);

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