Heatmap layer

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

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


Принцип работы heatmap слоя

Heatmap слой в Mapbox GL JS строится на основе источника данных типа GeoJSON. Каждая точка в наборе данных рассматривается как вклад в локальную плотность.

Ключевые характеристики:

  • каждая точка имеет «вес» (weight)
  • вклад точки распределяется в радиусе влияния
  • итоговое значение зависит от плотности соседних точек
  • результат визуализируется через цветовую шкалу

Математически слой можно представить как взвешенную сумму гауссовых функций, центрированных в каждой точке:

f(x) = _{i=1}^{n} w_i e^{-}

где:

  • ( w_i ) — вес точки
  • ( d(x,x_i) ) — расстояние до точки
  • ( ) — радиус влияния

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

Heatmap слой создаётся через map.addLayer после добавления источника данных.

map.on('load', () => {
  map.addSource('events', {
    type: 'geojson',
    data: '/data/events.geojson'
  });

  map.addLayer({
    id: 'events-heat',
    type: 'heatmap',
    source: 'events',
    maxzoom: 15,
    paint: {
      'heatmap-weight': 1,
      'heatmap-intensity': 1,
      'heatmap-radius': 20,
      'heatmap-opacity': 1
    }
  });
});

Источник данных и структура GeoJSON

Heatmap слой работает только с точечными геометриями.

Пример структуры:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "weight": 0.8
      },
      "geometry": {
        "type": "Point",
        "coordinates": [71.445, 51.169]
      }
    }
  ]
}

Поле properties.weight используется для управления вкладом точки в плотность.


Основные параметры heatmap слоя

heatmap-weight

Определяет вклад каждой точки в общую плотность.

'heatmap-weight': [
  'interpolate',
  ['linear'],
  ['get', 'weight'],
  0, 0,
  1, 1
]

Применяется для:

  • усиления значимости определённых объектов
  • дифференциации типов событий
  • нормализации данных

heatmap-intensity

Контролирует общую «яркость» слоя.

'heatmap-intensity': [
  'interpolate',
  ['linear'],
  ['zoom'],
  0, 1,
  9, 3
]

Особенности:

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

heatmap-radius

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

'heatmap-radius': [
  'interpolate',
  ['linear'],
  ['zoom'],
  0, 2,
  9, 30
]

При увеличении:

  • точки «размываются» сильнее
  • возрастает зона перекрытия
  • формируются крупные кластеры плотности

heatmap-opacity

Управляет прозрачностью слоя.

'heatmap-opacity': [
  'interpolate',
  ['linear'],
  ['zoom'],
  7, 1,
  15, 0
]

Часто используется для:

  • плавного перехода к точечному слою
  • комбинирования с circle layer
  • создания многослойных визуализаций

Цветовая шкала heatmap

Цветовая визуализация задаётся через heatmap-color, основанную на интерполяции плотности.

'heatmap-color': [
  'interpolate',
  ['linear'],
  ['heatmap-density'],
  0, 'rgba(0,0,255,0)',
  0.2, 'blue',
  0.4, 'cyan',
  0.6, 'lime',
  0.8, 'yellow',
  1, 'red'
]

Здесь используется внутренний показатель:

  • heatmap-density — нормализованная плотность (0–1)

Типичные схемы:

  • холодные цвета для низкой плотности
  • тёплые для высокой концентрации

Адаптация под масштаб карты

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

Пример зависимости:

'heatmap-radius': [
  'interpolate',
  ['exponential', 2],
  ['zoom'],
  0, 1,
  12, 40
]

Поведение:

  • при малом масштабе — крупные размытые зоны
  • при увеличении — более точные локальные кластеры

Комбинирование с circle layer

Часто heatmap используется совместно с точечным слоем для детализации на высоком зуме.

map.addLayer({
  id: 'points',
  type: 'circle',
  source: 'events',
  minzoom: 12,
  paint: {
    'circle-radius': 4,
    'circle-color': 'blue'
  }
});

Логика разделения:

  • heatmap: глобальная картина
  • circle: точные координаты

Фильтрация данных в heatmap

Можно ограничивать набор данных через фильтры:

map.setFilter('events-heat', [
  '==',
  ['get', 'type'],
  'incident'
]);

Применяется для:

  • сегментации событий
  • выделения категорий
  • динамического анализа

Производительность heatmap слоя

Heatmap слой оптимизирован для большого количества точек, но требует учета:

  • GeoJSON больших размеров замедляет загрузку
  • интенсивные вычисления происходят на GPU
  • чрезмерный радиус снижает производительность

Рекомендации:

  • использовать vector tiles при больших данных
  • ограничивать zoom диапазон слоя
  • уменьшать плотность данных через pre-aggregation

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

Heatmap слой не предоставляет прямого взаимодействия с отдельными точками, но можно использовать queryRenderedFeatures.

map.on('click', (e) => {
  const features = map.queryRenderedFeatures(e.point, {
    layers: ['events-heat']
  });

  console.log(features);
});

Часто используется для:

  • определения зоны интереса
  • перехода к детализации
  • отображения информации о регионе

Использование экспрессий для динамики

Mapbox GL JS поддерживает выражения для адаптивного управления heatmap параметрами.

Пример зависимости от свойства:

'heatmap-weight': [
  'match',
  ['get', 'severity'],
  'low', 0.2,
  'medium', 0.6,
  'high', 1,
  0
]

Это позволяет:

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

Типовые сценарии применения

Heatmap слой применяется в аналитических задачах:

  • анализ дорожного трафика
  • визуализация преступности
  • распределение пользователей
  • тепловые карты продаж
  • мониторинг сенсорных данных

В экосистеме Mapbox он часто используется как первый уровень визуализации перед переходом к детализированным слоям.


Ограничения модели heatmap

Несмотря на гибкость, слой имеет ограничения:

  • невозможность точного отображения единичных объектов
  • зависимость от плотности данных
  • визуальная агрегация скрывает индивидуальные точки
  • ограниченная интерпретируемость при низком масштабе

Эти ограничения компенсируются комбинированием слоёв и настройкой параметров интерполяции.