Класс CircleMarker

Общая концепция CircleMarker

CircleMarker в Leaflet представляет собой векторный слой, отображающий круг на карте с радиусом, заданным в пикселях экрана. Это ключевое отличие от обычного Circle, радиус которого задаётся в метрах и привязан к географическому масштабу.

Основная особенность CircleMarker:

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

Такой подход делает CircleMarker удобным для отображения:

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

Создание CircleMarker

Базовый синтаксис:

L.circleMarker(latlng, options)

или через конструктор:

new L.CircleMarker(latlng, options)

Пример создания

const marker = L.circleMarker([55.751244, 37.618423], {
  radius: 10,
  color: '#3388ff',
  weight: 2,
  fillColor: '#3388ff',
  fillOpacity: 0.5
}).addTo(map);

Ключевое отличие от Circle

Свойство Circle CircleMarker
Радиус метры пиксели
Масштабирование изменяется с zoom фиксированный размер
Геометрический смысл географический радиус экранная точка
Использование зоны, покрытия маркеры, события

Опции CircleMarker

CircleMarker наследует опции от Path и добавляет специфические параметры.

Основные опции

{
  radius: 10,               // радиус в пикселях
  stroke: true,             // отображать обводку
  color: '#3388ff',         // цвет обводки
  weight: 3,                // толщина линии
  opacity: 1.0,             // прозрачность обводки
  fill: true,              // заливка
  fillColor: '#3388ff',     // цвет заливки
  fillOpacity: 0.2,         // прозрачность заливки
  lineCap: 'round',         // стиль концов линии
  lineJoin: 'round',        // соединение линий
  dashArray: null,          // пунктирная линия
  dashOffset: null,         // смещение штриха
  interactive: true         // интерактивность слоя
}

Радиус и визуальное поведение

Радиус в пикселях

L.circleMarker([51.5, -0.09], {
  radius: 20
}).addTo(map);
  • 20 пикселей всегда остаётся 20 пикселей
  • при увеличении масштаба карта увеличивается, но круг остаётся визуально одинаковым

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


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

const circle = L.circleMarker([48.8566, 2.3522], {
  radius: 8,
  color: 'red',
  fillColor: 'red',
  fillOpacity: 0.6
});

circle.addTo(map);

или сразу:

L.circleMarker([48.8566, 2.3522], {
  radius: 8
}).addTo(map);

Работа с событиями

CircleMarker поддерживает стандартные события Leaflet:

circle.on('click', function (e) {
  console.log('Клик по CircleMarker');
});

Часто используемые события

  • click
  • mouseover
  • mouseout
  • mousedown
  • mouseup
  • contextmenu

Пример наведения

circle.on('mouseover', () => {
  circle.setStyle({
    fillColor: 'orange'
  });
});

circle.on('mouseout', () => {
  circle.setStyle({
    fillColor: 'red'
  });
});

Изменение стиля через setStyle

Метод setStyle позволяет динамически менять внешний вид:

circle.setStyle({
  color: 'green',
  fillColor: 'green',
  fillOpacity: 0.4
});

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

  • изменения применяются без пересоздания слоя
  • поддерживает частичное обновление свойств

Получение и изменение радиуса

circle.setRadius(15);
console.log(circle.getRadius());
  • setRadius(value) — изменение радиуса
  • getRadius() — получение текущего значения

Привязка всплывающих окон и tooltip

circle.bindPopup('Объект на карте');

Tooltip

circle.bindTooltip('Точка интереса', {
  direction: 'top'
});

Использование в аналитике данных

CircleMarker часто применяется для визуализации данных:

Пример отображения массива точек

const points = [
  [55.75, 37.61],
  [55.76, 37.64],
  [55.72, 37.58]
];

points.forEach(p => {
  L.circleMarker(p, {
    radius: 6,
    color: '#2c7bb6',
    fillOpacity: 0.7
  }).addTo(map);
});

Динамическое изменение радиуса по данным

Часто радиус зависит от значения:

function getRadius(value) {
  return Math.sqrt(value) * 2;
}

L.circleMarker([55.75, 37.61], {
  radius: getRadius(100)
}).addTo(map);

Такой подход используется для:

  • визуализации плотности
  • отображения статистики
  • сравнительного анализа объектов

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

CircleMarker относится к SVG/VML (в зависимости от браузера), что влияет на производительность:

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

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

Оптимизация

  • уменьшение количества DOM-элементов
  • использование кластеризации (например, marker clustering)
  • упрощение стилей (без теней и сложных градиентов)

Взаимодействие с масштабом карты

Хотя радиус фиксирован, позиция всегда пересчитывается:

  • при zoom происходит перерасчёт координат
  • размер остаётся неизменным
  • создаётся эффект “прикреплённой точки”

Это делает CircleMarker удобным для UI-слоёв, но не для географических зон.


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

circle.remove();

или

map.removeLayer(circle);

Проверка наличия на карте:

map.hasLayer(circle);

Работа с z-index

Для управления перекрытием:

circle.setZIndexOffset(1000);

Используется, когда:

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

Использование в связке с GeoJSON

L.geoJSON(data, {
  pointToLayer: function (feature, latlng) {
    return L.circleMarker(latlng, {
      radius: 5,
      fillColor: '#ff7800',
      color: '#000',
      weight: 1,
      fillOpacity: 0.8
    });
  }
}).addTo(map);

Отличия поведения при масштабировании

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

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

Это может приводить к эффектам:

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

Практические сценарии применения

  • отображение точек пользователей
  • события в системах мониторинга
  • визуализация логов по координатам
  • heatmap-альтернативы (упрощённые)
  • UI-индикаторы на карте

Ограничения CircleMarker

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

Внутреннее поведение рендеринга

CircleMarker создаётся как SVG circle элемент:

  • пересчитывает координаты при каждом zoomend
  • применяет трансформации через Leaflet renderer
  • обновляет атрибуты cx, cy, r

В Canvas-режиме поведение аналогично, но через рисование на контексте.


Связь с архитектурой Leaflet

CircleMarker наследуется по цепочке:

  • Layer
  • Interactive layer
  • Path
  • CircleMarker

Это даёт:

  • доступ к событиям
  • поддержку стилей Path
  • интеграцию с renderer API