Редактирование геометрии в MapLibre GL JS опирается на работу с источниками данных типа GeoJSON и динамическое обновление отображаемых объектов через механизм перерисовки слоёв. Вся интерактивная логика строится вокруг преобразования пользовательских действий (клик, перемещение курсора, перетаскивание) в модификации геометрии и последующую передачу обновлённого состояния в источник данных карты.
В MapLibre GL JS геометрические объекты представлены в формате
GeoJSON, где каждая сущность описывается как Feature с координатами и
свойствами. Источник данных типа geojson используется как
центральный контейнер редактируемых объектов.
Ключевая особенность подхода заключается в том, что геометрия не изменяется «на месте» внутри карты. Вместо этого формируется новая версия данных, которая целиком передаётся в источник:
map.getSource('draw-layer').setData(geojson);
Такая модель обеспечивает предсказуемость состояния и упрощает синхронизацию интерфейса с данными.
Каждое обновление GeoJSON вызывает пересчёт всех зависимых слоёв. Внутренний конвейер MapLibre выполняет:
Частые вызовы setData становятся критическим фактором
производительности, поэтому при редактировании геометрии применяется
пакетирование изменений или локальное накопление состояния перед
обновлением источника.
Редактирование геометрии реализуется через низкоуровневые события карты:
mousedown — начало захвата вершины или объекта;mousemove — изменение координат;mouseup — фиксация результата;click — выбор объекта или вершины.Перемещение координат осуществляется через преобразование экранных координат в географические:
const lngLat = map.unproject([e.point.x, e.point.y]);
Этот механизм является основой любого редактора геометрии поверх MapLibre GL JS.
Точечные объекты являются наиболее простым случаем редактирования. Геометрия представлена одной парой координат, которая полностью заменяется при каждом перемещении.
Алгоритм включает:
feature.geometry.coordinates = [lng, lat];
source.setData(data);
Для повышения отзывчивости часто используется промежуточное состояние
без немедленного обновления источника на каждом событии
mousemove, с применением throttling.
Линии (LineString) требуют управления массивом координат. Основные операции:
При захвате вершины фиксируется её индекс в массиве координат. В процессе перетаскивания изменяется только соответствующий элемент:
coordinates[index] = [lng, lat];
Добавление новой вершины обычно выполняется вставкой между ближайшими сегментами линии с пересборкой массива координат.
Особое внимание требуется уделять сохранению непрерывности геометрии и предотвращению самопересечений при сложных сценариях редактирования.
Полигональные геометрии обладают дополнительной сложностью из-за наличия замкнутого контура и возможных внутренних колец (holes).
Структура координат:
coordinates[0];coordinates[1..n].Редактирование включает:
При изменении вершины требуется синхронное обновление первой и последней точки контура, поскольку они совпадают:
ring[ring.length - 1] = ring[0];
Для внутренних колец применяются те же правила, но без обязательного замыкания при каждом изменении, если это компенсируется на этапе валидации.
MapLibre GL JS поддерживает механизм FeatureState,
позволяющий хранить временное состояние объектов без изменения
GeoJSON:
map.setFeatureState(
{ source: 'draw', id: featureId },
{ active: true }
);
Этот механизм используется для разделения визуального состояния и геометрических данных, снижая частоту пересборки источника.
Редактирование вершин основано на комбинации hit-testing и событий мыши. Определение активной вершины выполняется через анализ близости курсора к экранным координатам вершин.
Общий алгоритм:
Для повышения производительности применяется пространственная индексация или кэширование экранных координат до начала взаимодействия.
В процессе редактирования часто применяется привязка координат:
Механизм снаппинга реализуется через округление координат или поиск ближайших объектов в заданном радиусе:
lng = Math.round(lng * precision) / precision;
lat = Math.round(lat * precision) / precision;
Дополнительно могут применяться геометрические ограничения, например запрет выхода за заданный bounding box или сохранение топологической корректности.
Поверх базового API часто используется расширение MapLibre GL Draw, реализующее полноценный редактор геометрии. Оно предоставляет:
Внутренне библиотека использует отдельные interaction modes, каждый из которых управляет состоянием редактора и интерпретацией событий карты.
Архитектура строится вокруг состояния:
selected feature;active vertex;mode (draw, direct_select, simple_select).Редактирование геометрии является чувствительным к производительности из-за высокой частоты событий мыши и пересчёта слоёв.
Основные оптимизации:
setData;При больших наборах данных применяется разделение редактируемых и статических слоёв.
Построение собственного редактора поверх MapLibre GL JS обычно опирается на следующие компоненты:
Состояние геометрии часто хранится отдельно от источника карты и синхронизируется через явные коммиты изменений, что позволяет реализовать undo/redo и временные транзакции редактирования.
Для поддержки отмены действий применяется хранение снимков состояния GeoJSON или журнал операций:
Каждое действие описывается как операция над структурой координат, что позволяет восстанавливать предыдущее состояние без полного пересчёта данных.
Редактирование геометрии в MapLibre GL JS обычно сводится к следующим операциям:
Все сценарии объединяются общей моделью: изменение координат → пересборка GeoJSON → обновление источника → перерисовка слоёв.