Circle

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

Работа слоя основана на источнике данных (source), который предоставляет набор точек в формате GeoJSON. Каждая точка преобразуется в круг, параметры которого задаются через свойства слоя.


Перед созданием визуализации необходимо определить источник данных:

map.addSource('points', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [71.4304, 51.1282]
        },
        properties: {
          magnitude: 5.2
        }
      }
    ]
  }
});

Далее добавляется слой типа circle:

map.addLayer({
  id: 'circle-layer',
  type: 'circle',
  source: 'points'
});

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


Геометрическая интерпретация круга

Каждая точка GeoJSON интерпретируется как центр окружности в координатах карты. Радиус круга задаётся не в географических единицах, а в пикселях экрана, что делает визуализацию зависимой от масштаба.

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


Основные свойства визуализации

Радиус круга

circle-radius определяет размер отображаемого круга:

map.setPaintProperty('circle-layer', 'circle-radius', 8);

Также поддерживается масштабозависимое изменение:

map.setPaintProperty('circle-layer', 'circle-radius', [
  'interpolate',
  ['linear'],
  ['zoom'],
  5, 2,
  10, 6,
  15, 20
]);

При низком зуме точки визуально уменьшаются, при высоком — увеличиваются.


Цвет заливки

circle-color задаёт цвет заполнения:

map.setPaintProperty('circle-layer', 'circle-color', '#3b82f6');

Поддерживаются выражения на основе свойств данных:

map.setPaintProperty('circle-layer', 'circle-color', [
  'case',
  ['>=', ['get', 'magnitude'], 5], '#ef4444',
  '#22c55e'
]);

Это позволяет визуализировать категориальные или числовые признаки.


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

circle-opacity управляет видимостью:

map.setPaintProperty('circle-layer', 'circle-opacity', 0.7);

Можно комбинировать с условиями:

map.setPaintProperty('circle-layer', 'circle-opacity', [
  'interpolate',
  ['linear'],
  ['zoom'],
  5, 0.3,
  12, 0.8
]);

Обводка круга

Круги могут иметь контур:

map.setPaintProperty('circle-layer', 'circle-stroke-color', '#111827');
map.setPaintProperty('circle-layer', 'circle-stroke-width', 1);

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

map.setPaintProperty('circle-layer', 'circle-stroke-opacity', 0.5);

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


Размытие и визуальная мягкость

circle-blur задаёт степень размытия края круга:

map.setPaintProperty('circle-layer', 'circle-blur', 0.2);

Значение 0 даёт резкую границу, значения ближе к 1 создают эффект свечения и мягкого пятна.

Этот параметр часто используется для:

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

Смещение и позиционирование

circle-translate позволяет смещать круг относительно координаты точки:

map.setPaintProperty('circle-layer', 'circle-translate', [10, 10]);

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

circle-translate-anchor определяет систему координат смещения:

  • map — смещение в координатах карты
  • viewport — смещение относительно экрана

Данные и визуальная динамика

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

Визуализация по числовым значениям

map.setPaintProperty('circle-layer', 'circle-radius', [
  'interpolate',
  ['linear'],
  ['get', 'magnitude'],
  1, 2,
  5, 10,
  10, 20
]);

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


Категориальная окраска

map.setPaintProperty('circle-layer', 'circle-color', [
  'match',
  ['get', 'type'],
  'earthquake', '#ef4444',
  'aftershock', '#f97316',
  '#3b82f6'
]);

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


Работа с масштабом (zoom)

Визуализация часто требует адаптации к уровню приближения.

Плавное изменение размеров

map.setPaintProperty('circle-layer', 'circle-radius', [
  'interpolate',
  ['exponential', 1.5],
  ['zoom'],
  3, 1,
  8, 4,
  14, 12
]);

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


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

map.setPaintProperty('circle-layer', 'circle-opacity', [
  'step',
  ['zoom'],
  0,
  6, 1
]);

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


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

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

Наведение курсора

map.on('mouseenter', 'circle-layer', (e) => {
  map.getCanvas().style.cursor = 'pointer';
});

Клик по точке

map.on('click', 'circle-layer', (e) => {
  const feature = e.features[0];
  console.log(feature.properties);
});

Извлечение объектов

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

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


Кластеризация и масштабируемость

При больших наборах данных используется кластеризация:

map.addSource('points', {
  type: 'geojson',
  data: geojsonData,
  cluster: true,
  clusterMaxZoom: 14,
  clusterRadius: 50
});

Кластеры также можно визуализировать через circle слой:

map.addLayer({
  id: 'clusters',
  type: 'circle',
  source: 'points',
  filter: ['has', 'point_count'],
  paint: {
    'circle-color': '#6366f1',
    'circle-radius': [
      'step',
      ['get', 'point_count'],
      10,
      10, 15,
      50, 25
    ]
  }
});

Отдельный слой для одиночных точек:

map.addLayer({
  id: 'unclustered',
  type: 'circle',
  source: 'points',
  filter: ['!', ['has', 'point_count']],
  paint: {
    'circle-color': '#22c55e',
    'circle-radius': 5
  }
});

Производительность и оптимизация

При работе с большим количеством точек важны следующие аспекты:

Использование кластеризации снижает количество отрисовываемых объектов. Минимизация количества выражений в paint ускоряет рендеринг. Избегание чрезмерного использования прозрачности и blur уменьшает нагрузку на GPU.

Также важна структура GeoJSON: плоские и компактные свойства ускоряют обработку.


Комбинация с другими слоями

Circle слой часто используется совместно с:

  • symbol для подписей
  • heatmap для плотности
  • fill для региональных данных

Пример комбинированной визуализации:

map.addLayer({
  id: 'points-glow',
  type: 'circle',
  source: 'points',
  paint: {
    'circle-radius': 10,
    'circle-color': '#60a5fa',
    'circle-blur': 0.4,
    'circle-opacity': 0.5
  }
});

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


Выражения и логика стилей

Mapbox GL JS поддерживает функциональные выражения, позволяющие строить сложные правила визуализации:

  • get — доступ к свойствам
  • case — условная логика
  • match — сопоставление значений
  • interpolate — плавные переходы
  • step — ступенчатые функции

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