Редактирование геометрии в интерактивных веб-картах опирается на управление векторными слоями, изменением координатных наборов и синхронизацией состояния между визуальным представлением и моделью данных. В Leaflet базовые примитивы (маркер, полилиния, полигон, прямоугольник, круг) изначально предназначены для отображения геометрии, однако полноценное редактирование требует включения дополнительных механизмов и расширений.
Основная модель редактирования строится вокруг изменения массива
координат объектов LatLng, который лежит в основе всех
векторных слоёв. Любое редактирование сводится к добавлению, удалению
или изменению элементов этого массива с последующим перерисовыванием
слоя.
Каждый геометрический объект в Leaflet представляет собой слой с набором координат:
L.Marker — одна точка (LatLng)L.Polyline — массив точек (ломаная линия)L.Polygon — замкнутый массив точекL.Rectangle — производная от полигона с фиксированной
геометриейL.Circle — центр + радиусРедактирование начинается с доступа к этим параметрам:
const polyline = L.polyline([
[55.75, 37.61],
[55.76, 37.62]
]).addTo(map);
const latlngs = polyline.getLatLngs();
Изменение геометрии напрямую:
latlngs.push(L.latLng(55.77, 37.63));
polyline.setLatLngs(latlngs);
Такой подход является базовым, но не предоставляет интерактивности.
Маркер является минимальной единицей редактирования, поскольку его геометрия — одна точка.
const marker = L.marker([55.75, 37.61], {
draggable: true
}).addTo(map);
marker.on('dragend', (e) => {
const position = e.target.getLatLng();
});
Ключевой механизм — свойство draggable. Оно переводит
слой в режим изменения координат через события мыши или касания.
События:
dragstartdragdragendМаркер не требует пересчёта геометрии, так как изменяется единственная точка.
Полилинии и полигоны требуют работы с множеством вершин. В стандартном API Leaflet отсутствует полноценный UI для редактирования, поэтому применяется механизм расширения через плагины или ручная реализация.
const polygon = L.polygon([
[55.75, 37.61],
[55.76, 37.62],
[55.75, 37.63]
]).addTo(map);
const coords = polygon.getLatLngs()[0];
coords[0] = L.latLng(55.751, 37.611);
polygon.setLatLngs(coords);
Такой подход требует постоянного контроля структуры массива.
Наиболее распространённый механизм редактирования реализуется через библиотеку Leaflet.draw:
Она добавляет инструменты рисования и редактирования геометрии.
const drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
const drawControl = new L.Control.Draw({
edit: {
featureGroup: drawnItems
},
draw: {
polygon: true,
polyline: true,
rectangle: true,
circle: true,
marker: true
}
});
map.addControl(drawControl);
map.on(L.Draw.Event.CREATED, function (e) {
const layer = e.layer;
drawnItems.addLayer(layer);
});
После добавления слоя он становится доступным для редактирования через встроенные инструменты.
Редактируемые слои генерируют набор событий, позволяющих отслеживать изменения:
editstartediteditendПример:
polygon.on('edit', (e) => {
const updated = e.target.getLatLngs();
});
Эти события критичны для синхронизации с сервером или локальным хранилищем.
Альтернативный подход реализуется через плагин Leaflet.Editable, который вводит режимы:
map.editTools.startPolygon();
После активации режимов каждый слой становится интерактивным без дополнительного UI.
Редактирование полигонов и полилиний опирается на операции с вершинами:
coords.splice(index, 0, L.latLng(55.755, 37.615));
polygon.setLatLngs(coords);
coords.splice(index, 1);
polygon.setLatLngs(coords);
coords[index] = L.latLng(newLat, newLng);
polygon.setLatLngs(coords);
Каждое изменение требует полной синхронизации массива координат с объектом слоя.
Интерактивное редактирование реализуется через вспомогательные маркеры, которые представляют вершины геометрии.
function enableVertexEditing(polygon) {
const latlngs = polygon.getLatLngs()[0];
latlngs.forEach((point, index) => {
const handle = L.marker(point, { draggable: true }).addTo(map);
handle.on('drag', (e) => {
latlngs[index] = e.target.getLatLng();
polygon.setLatLngs(latlngs);
});
});
}
Такой механизм является базой для кастомных редакторов геометрии.
Полигоны могут содержать несколько колец (outer ring + holes):
const polygon = L.polygon([
[
[55.75, 37.61],
[55.76, 37.62],
[55.75, 37.63]
],
[
[55.755, 37.615],
[55.756, 37.616],
[55.755, 37.617]
]
]);
Редактирование таких структур требует учёта уровней вложенности:
latlngs[0]latlngs[1..n]Редактируемые слои часто конвертируются в GeoJSON для хранения:
const geojson = polygon.toGeoJSON();
Обратное восстановление:
L.geoJSON(geojson, {
onEachFeature: function (feature, layer) {
layer.editing.enable();
}
}).addTo(map);
GeoJSON становится универсальным форматом для обмена геометрией между клиентом и сервером.
Редактирование геометрии в Leaflet имеет ряд технических ограничений:
setLatLngs создают нагрузку на DOM и
canvasДля оптимизации применяются:
Редактирование может быть расширено дополнительными механизмами:
Пример ограничения перемещения маркера:
marker.on('drag', (e) => {
const latlng = e.target.getLatLng();
if (latlng.lat > 60) {
e.target.setLatLng([60, latlng.lng]);
}
});
Редактирование векторной геометрии в Leaflet можно рассматривать как цикл:
LatLngsetLatLngsЭтот цикл является фундаментом всех систем интерактивного картографического редактирования на базе Leaflet.