Circle: круги

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

Круги реализуются через класс L.circle, который наследуется от базового слоя Path. Это означает, что они обладают всеми возможностями векторной графики Leaflet: стилизацией, обработкой событий, привязкой всплывающих окон и подсказок.


Создание круга

Базовая конструкция круга задаётся координатами центра и радиусом:

L.circle([55.751244, 37.618423], {
    radius: 1000
}).addTo(map);

Первый аргумент — географические координаты центра [lat, lng]. Второй — объект настроек, где ключевым параметром является radius, измеряемый в метрах.

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


Основные параметры Circle

Объект настроек поддерживает те же стилистические свойства, что и полилинии и полигоны:

  • color — цвет обводки
  • weight — толщина линии
  • opacity — прозрачность обводки
  • fillColor — цвет заливки
  • fillOpacity — прозрачность заливки
  • dashArray — пунктирная линия
  • lineCap, lineJoin — стиль соединений линий

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

L.circle([55.75, 37.61], {
    radius: 2000,
    color: '#2c3e50',
    weight: 2,
    fillColor: '#3498db',
    fillOpacity: 0.3
}).addTo(map);

Географический смысл радиуса

Радиус круга интерпретируется в метрах и зависит от используемой проекции карты. Leaflet использует Web Mercator, где расстояния искажаются на высоких широтах, однако для большинства задач визуализации (зоны покрытия, радиусы поиска, области влияния) погрешность остаётся допустимой.

Ключевая особенность:

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

Отличие Circle и CircleMarker

В Leaflet существует два похожих объекта: L.circle и L.circleMarker.

L.circle

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

L.circleMarker

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

Пример CircleMarker:

L.circleMarker([55.751244, 37.618423], {
    radius: 10
}).addTo(map);

Различие принципиально: Circle описывает реальную область на карте, CircleMarker — экранный элемент интерфейса.


Управление объектом Circle

Созданный круг представляет собой слой (Layer), который можно динамически изменять.

Изменение радиуса

circle.setRadius(5000);

Изменение центра

circle.setLatLng([55.76, 37.64]);

Получение параметров

circle.getRadius();
circle.getLatLng();

События круга

Круги поддерживают стандартную систему событий Leaflet:

  • click
  • mouseover
  • mouseout
  • mousedown
  • mouseup

Пример обработки клика:

circle.on('click', function (e) {
    console.log('Круг нажат', e.latlng);
});

События позволяют использовать круги как интерактивные зоны: выделение областей, отображение информации, запуск логики приложения.


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

Круги поддерживают привязку popups и tooltips:

L.circle([55.75, 37.61], {
    radius: 1500
})
.bindPopup('Зона покрытия')
.addTo(map);

Tooltip:

circle.bindTooltip('Радиус 1500 м');

Popup открывается по клику, tooltip — при наведении.


Работа с GeoJSON

Circle не является стандартной GeoJSON-геометрией, однако Leaflet позволяет представлять его через Point с дополнительными свойствами.

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

L.geoJSON(feature, {
    pointToLayer: function (feature, latlng) {
        return L.circle(latlng, {
            radius: feature.properties.radius
        });
    }
}).addTo(map);

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


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

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

Пример обновления в цикле:

function updateCircle(value) {
    circle.setRadius(value);
}

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


Взаимодействие с картой и слоями

Круг является полноценным слоем и участвует в системе управления слоями Leaflet:

circle.addTo(map);
map.removeLayer(circle);

Также он может быть включён в группы:

const group = L.layerGroup([circle1, circle2]);
group.addTo(map);

Это важно при работе с большим количеством геометрии.


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

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

  • сложности заливки (fillOpacity, fillColor)
  • наличия обводки
  • количества перерисовок при зуме
  • использования SVG или Canvas renderer

Leaflet по умолчанию использует SVG, однако при масштабных данных возможен переход на Canvas:

const map = L.map('map', {
    preferCanvas: true
});

Canvas-рендерер снижает нагрузку при массовом отображении кругов.


Стилизация через функции

Параметры круга могут задаваться динамически:

function getColor(radius) {
    return radius > 1000 ? 'red' : 'green';
}

L.circle([55.75, 37.61], {
    radius: 2000,
    color: getColor(2000)
}).addTo(map);

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


Вложенные сценарии использования

Круги применяются для моделирования пространственных областей:

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

Каждый круг выступает как визуальное представление числовой модели.


Изменение внешнего вида при взаимодействии

Состояние круга может меняться при событиях:

circle.on('mouseover', function () {
    this.setStyle({
        fillOpacity: 0.6
    });
});

circle.on('mouseout', function () {
    this.setStyle({
        fillOpacity: 0.3
    });
});

Метод setStyle доступен благодаря наследованию от Path.


Ограничения и особенности

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

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

Круги часто используются совместно с маркерами:

L.marker([55.75, 37.61]).addTo(map);
L.circle([55.75, 37.61], { radius: 1000 }).addTo(map);

Маркер обозначает точку, круг — область вокруг неё. Такое сочетание формирует базовую структуру пространственной визуализации.


Анимация изменения радиуса

Leaflet не предоставляет встроенной анимации, но изменение радиуса может быть реализовано через интерполяцию:

let r = 100;

const interval = setInterval(() => {
    r += 100;
    circle.setRadius(r);

    if (r >= 2000) clearInterval(interval);
}, 100);

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


Работа с множественными кругами

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

const centers = [
    [55.75, 37.61],
    [55.76, 37.62],
    [55.74, 37.60]
];

centers.forEach(c => {
    L.circle(c, {
        radius: 800
    }).addTo(map);
});

Такие структуры формируют плотностные зоны или кластеры покрытия.