Heatmap слой

Heatmap слой в MapLibre GL JS используется для визуализации плотности точек на карте. Вместо отображения отдельных маркеров данные агрегируются в непрерывное поле интенсивности, где цвет и яркость зависят от концентрации объектов в пространстве. Такой подход особенно эффективен при работе с большими наборами геоданных, где визуальное восприятие отдельных точек теряет информативность.

В MapLibre GL JS heatmap реализуется как отдельный тип слоя, работающий на основе источника данных GeoJSON. Каждая точка интерпретируется как вклад в локальную плотность, которая затем интерполируется в пиксельное изображение.


Источник данных для heatmap слоя

Heatmap слой всегда опирается на источник типа geojson. Каждая точка должна быть представлена в формате Point.

Пример базового источника:

map.addSource('earthquakes', {
  type: 'geojson',
  data: 'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson'
});

Каждый объект внутри набора данных обычно содержит свойства, влияющие на визуализацию: магнитуду, категорию, вес или другие числовые характеристики.


Создание heatmap слоя

Heatmap слой добавляется после подключения источника данных. Важно, чтобы слой ссылался на существующий источник через source.

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

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


Вес точек (heatmap-weight)

Свойство heatmap-weight определяет вклад каждой точки в общую плотность. Оно может быть фиксированным или зависеть от атрибута данных.

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

В этом примере значение магнитуды (mag) нормализуется в диапазон от 0 до 1. Более высокие значения усиливают влияние точки на тепловую карту.


Интенсивность тепловой карты

heatmap-intensity управляет общим масштабированием плотности. Этот параметр особенно важен при зуме карты, поскольку плотность точек визуально меняется при изменении масштаба.

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

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


Радиус влияния точек

heatmap-radius определяет область воздействия каждой точки. Чем больше радиус, тем более сглаженной становится карта.

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

Малые значения создают локальные «пятна», большие — формируют плавные области плотности.


Прозрачность слоя

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

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

Типичный подход — постепенное исчезновение heatmap при увеличении масштаба, уступая место точечному или кластерному слою.


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

Цвет задаётся через heatmap-color и формируется на основе интерполяции плотности. Обычно используется градиент от холодных к тёплым цветам.

'heatmap-color': [
  'interpolate',
  ['linear'],
  ['heatmap-density'],
  0, 'rgba(33,102,172,0)',
  0.2, 'rgb(103,169,207)',
  0.4, 'rgb(209,229,240)',
  0.6, 'rgb(253,219,199)',
  0.8, 'rgb(239,138,98)',
  1, 'rgb(178,24,43)'
]

heatmap-density — встроенная функция MapLibre, возвращающая нормализованную плотность в каждой точке растрового представления.


Зависимость от зума

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

Типичная стратегия:

  • zoom 0–6: только heatmap
  • zoom 6–9: комбинированное отображение
  • zoom 9+: точки или кластеры

Комбинация heatmap и circle слоя

Часто heatmap используется вместе с circle слоем, который показывает отдельные точки при увеличении масштаба.

map.addLayer({
  id: 'earthquakes-point',
  type: 'circle',
  source: 'earthquakes',
  minzoom: 7,
  paint: {
    'circle-radius': 4,
    'circle-color': 'rgb(0, 0, 0)'
  }
});

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


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

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

filter: ['>', ['get', 'mag'], 2]

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


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

Heatmap слой является GPU-ускоренным и обрабатывается на стороне рендеринга, однако производительность зависит от нескольких факторов:

  • количество точек в GeoJSON
  • сложность выражений paint
  • частота обновления источника
  • уровень зума и пересчёт плотности

При больших объёмах данных целесообразно использовать:

  • серверную агрегацию
  • тайловые источники (vector tiles)
  • предварительное кластеризование

Кластеризация и heatmap

Heatmap часто сравнивается с кластеризацией, но эти подходы решают разные задачи.

Кластеризация группирует точки в дискретные объекты, heatmap формирует непрерывное поле.

MapLibre GL JS позволяет комбинировать оба подхода:

  • кластеризация на низких zoom уровнях
  • heatmap для плавной визуализации плотности
  • точки для точной локализации

Динамическое обновление данных

Источник heatmap может обновляться в реальном времени:

map.getSource('earthquakes').setData(newData);

Это позволяет строить визуализации потоковых данных, например:

  • сейсмическая активность
  • GPS-трекинг
  • события IoT

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


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

Heatmap слой активно использует выражения (expressions), позволяющие строить динамические зависимости:

  • interpolate
  • step
  • get
  • zoom
  • heatmap-density

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


Практическая структура heatmap слоя

Типовая конфигурация включает:

  • источник GeoJSON
  • heatmap слой (агрегация)
  • circle слой (детализация)
  • динамические зависимости от zoom

Такая архитектура позволяет масштабировать визуализацию от глобального обзора до точечного уровня без потери информации.