Класс Polygon

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

Внутренняя реализация Polygon наследуется от L.Polyline, что определяет общую структуру хранения координат и часть поведения, но добавляет ключевое отличие — автоматическое замыкание контура и работа с внутренними областями (holes).


Базовая структура и создание многоугольника

Многоугольник в Leaflet задаётся массивом координатных точек типа LatLng. Каждая точка представляет собой пару широта-долгота.

Синтаксис создания

L.polygon(latlngs, options)
  • latlngs — массив координат
  • options — объект параметров отображения

Простейший пример

const polygon = L.polygon([
  [55.751244, 37.618423],
  [55.761244, 37.628423],
  [55.751244, 37.638423]
]).addTo(map);

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


Структура координат

Leaflet поддерживает несколько уровней вложенности массива координат:

1. Простой многоугольник

[
  [lat, lng],
  [lat, lng],
  [lat, lng]
]

2. Многоугольник с отверстиями

[
  // внешний контур
  [
    [lat, lng],
    [lat, lng],
    [lat, lng]
  ],
  // внутренний контур (hole)
  [
    [lat, lng],
    [lat, lng],
    [lat, lng]
  ]
]

Первый массив определяет внешний периметр, последующие — вырезанные области внутри фигуры.


Параметры отображения (options)

Класс L.Polygon поддерживает широкий набор параметров стилизации, унаследованных от Path.

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

  • stroke — отображение обводки (true/false)
  • color — цвет линии
  • weight — толщина линии
  • opacity — прозрачность обводки
  • fill — включение заливки
  • fillColor — цвет заливки
  • fillOpacity — прозрачность заливки
  • dashArray — пунктирная линия
  • lineCap, lineJoin — стили соединений линий

Пример стилизации

const polygon = L.polygon([
  [55.75, 37.61],
  [55.76, 37.62],
  [55.75, 37.63]
], {
  color: 'blue',
  weight: 3,
  fillColor: '#3388ff',
  fillOpacity: 0.4
}).addTo(map);

Геометрические особенности

Замыкание контура

Polygon автоматически соединяет последнюю точку с первой. Это поведение не требует явного указания замыкающей координаты.

Самопересечения

При самопересекающихся полигонах визуализация зависит от алгоритма заполнения (winding rule). Leaflet не выполняет геометрическую коррекцию, поэтому результат отображения может быть неоднозначным.


Методы класса Polygon

Хотя Polygon наследует большинство методов от L.Path и L.Polyline, он имеет ряд специфичных операций.

setLatLngs

Обновляет координаты многоугольника.

polygon.setLatLngs([
  [55.75, 37.61],
  [55.76, 37.62],
  [55.75, 37.63]
]);

Поддерживает также вложенные массивы для работы с отверстиями.


getLatLngs

Возвращает текущие координаты.

const coords = polygon.getLatLngs();

Результат сохраняет структуру вложенности.


addLatLng

Добавляет новую точку в контур.

polygon.addLatLng([55.77, 37.64]);

При добавлении точек многоугольник динамически изменяет форму.


getBounds

Возвращает ограничивающий прямоугольник (bounding box), охватывающий весь полигон.

const bounds = polygon.getBounds();
map.fitBounds(bounds);

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


isEmpty

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

polygon.isEmpty();

Возвращает true, если координаты отсутствуют или массив пуст.


setStyle

Изменяет стили без пересоздания объекта.

polygon.setStyle({
  color: 'red',
  fillOpacity: 0.2
});

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


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

Polygon поддерживает стандартную систему событий Leaflet, унаследованную от L.Evented.

Основные события

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

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

polygon.on('click', function (e) {
  console.log('Клик по полигону', e.latlng);
});

События редактирования (при использовании плагинов)

При подключении Leaflet.draw или Leaflet.Editable появляются дополнительные события:

  • edit
  • editstart
  • editend
polygon.on('edit', function () {
  console.log('Полигон изменён');
});

Взаимодействие с GeoJSON

Polygon тесно интегрирован с форматом GeoJSON.

Создание из GeoJSON

const geojsonFeature = {
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [37.61, 55.75],
        [37.62, 55.76],
        [37.63, 55.75],
        [37.61, 55.75]
      ]
    ]
  }
};

L.geoJSON(geojsonFeature).addTo(map);

Важно учитывать, что GeoJSON использует порядок [lng, lat], тогда как Leaflet использует [lat, lng].


Преобразование Polygon в GeoJSON

const geo = polygon.toGeoJSON();

Результат можно сохранять или передавать на сервер.


Отверстия (holes) в полигонах

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

Пример полигона с отверстием

const polygon = L.polygon([
  [
    [55.78, 37.60],
    [55.78, 37.65],
    [55.73, 37.65],
    [55.73, 37.60]
  ],
  [
    [55.76, 37.61],
    [55.76, 37.64],
    [55.74, 37.64],
    [55.74, 37.61]
  ]
]).addTo(map);

Второй контур вырезается из первого.


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

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

Основные факторы влияния

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

Практики оптимизации

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

Отличие Polygon от Polyline

Хотя оба класса имеют общую основу, различия принципиальны:

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

Использование в слоях и группах

Polygon может быть добавлен в LayerGroup или FeatureGroup для управления набором объектов.

const group = L.featureGroup([polygon]).addTo(map);

map.fitBounds(group.getBounds());

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


Поведение при масштабировании карты

Polygon автоматически перерисовывается при изменении масштаба или центра карты. Векторная природа объекта обеспечивает сохранение качества при любом zoom-уровне.


Взаимодействие с CSS и DOM

Polygon не является DOM-элементом в классическом смысле. Он рендерится через SVG или Canvas (в зависимости от настроек карты). Это влияет на:

  • отсутствие прямого доступа к DOM-узлам формы
  • управление стилями только через API Leaflet
  • аппаратное ускорение в Canvas-режиме

Использование Canvas-рендерера

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

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

Polygon при этом отрисовывается быстрее, особенно при сложных геометриях.


Динамическое обновление формы

Polygon может изменять свою геометрию в реальном времени.

setInterval(() => {
  const latlngs = polygon.getLatLngs();
  latlngs[0][0][0] += 0.0001;
  polygon.setLatLngs(latlngs);
}, 1000);

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


Обработка взаимодействия с пользователем

Polygon часто используется для выделения областей на карте. При этом комбинируются события клика и визуальная обратная связь:

polygon.on('mouseover', () => {
  polygon.setStyle({ fillOpacity: 0.6 });
});

polygon.on('mouseout', () => {
  polygon.setStyle({ fillOpacity: 0.3 });
});

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