draw.create, draw.update, draw.delete

Mapbox GL JS в связке с расширением Mapbox GL Draw предоставляет механизм интерактивного рисования и редактирования геометрий на карте. События draw.create, draw.update, draw.delete являются ключевыми точками интеграции, через которые приложение получает уведомления о любых изменениях пользовательских объектов.

Mapbox GL Draw работает поверх слоя Mapbox GL JS и управляет GeoJSON-объектами. Каждое действие пользователя — создание, редактирование или удаление — транслируется в событие, которое отправляется на объект карты.

Основные сущности:

  • Feature (объект) — GeoJSON-геометрия с уникальным id
  • Collection (коллекция) — набор объектов
  • State (состояние) — текущее представление всех редактируемых объектов

Каждое изменение состояния приводит к генерации событий:

  • draw.create — добавление новых объектов
  • draw.update — изменение существующих объектов
  • draw.delete — удаление объектов

Событие draw.create

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

Объект события содержит массив созданных features:

map.on('draw.create', function (e) {
  console.log('Созданные объекты:', e.features);
});

Структура e.features:

[
  {
    "id": "abc123",
    "type": "Feature",
    "geometry": {
      "type": "Polygon",
      "coordinates": [...]
    },
    "properties": {}
  }
]

Особенности поведения

  • Срабатывает один раз после завершения рисования
  • При создании нескольких объектов подряд возвращает массив
  • Все объекты уже имеют назначенный id
  • Поддерживает Point, LineString, Polygon, Multi-geometries

Практическое использование

Типичный сценарий — сохранение новых объектов в базу данных:

map.on('draw.create', function (e) {
  const features = e.features;

  fetch('/api/features', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(features)
  });
});

Событие draw.update

Срабатывает при изменении уже существующих объектов. Изменения могут включать:

  • перемещение вершин
  • изменение формы полигона
  • редактирование линии
  • модификацию координат точки
map.on('draw.update', function (e) {
  console.log('Обновлённые объекты:', e.features);
});

Структура данных события

{
  "features": [
    {
      "id": "abc123",
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [...]
      },
      "properties": {}
    }
  ]
}

Характер поведения

  • Срабатывает при каждом изменении геометрии
  • Может вызываться многократно в процессе редактирования
  • Передаёт только изменённые features
  • Сохраняет идентичность id

Важные аспекты обработки

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

Оптимизация через debounce:

let timeout;

map.on('draw.update', function (e) {
  clearTimeout(timeout);

  timeout = setTimeout(() => {
    saveToServer(e.features);
  }, 300);
});

Событие draw.delete

Срабатывает при удалении одного или нескольких объектов из набора Draw.

map.on('draw.delete', function (e) {
  console.log('Удалённые объекты:', e.features);
});

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

  • Возвращает массив удалённых features
  • После удаления объекты больше недоступны через Draw API
  • Используется для синхронизации состояния с сервером

Пример обработки удаления

map.on('draw.delete', function (e) {
  const deletedIds = e.features.map(f => f.id);

  fetch('/api/features/delete', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ ids: deletedIds })
  });
});

Жизненный цикл объекта в Draw

Все три события образуют единый цикл управления геометрией:

  1. draw.create — объект появляется в системе
  2. draw.update — объект изменяется в процессе редактирования
  3. draw.delete — объект удаляется

Этот цикл повторяется для каждого feature независимо.

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

Mapbox GL Draw хранит внутреннее состояние, которое можно синхронизировать с внешними источниками данных.

Пример получения всех объектов:

const allFeatures = draw.getAll();

После чего события draw.update и draw.delete используются для поддержания актуальности внешнего хранилища.

Работа с множественными объектами

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

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

Пример множественного обновления:

map.on('draw.update', function (e) {
  e.features.forEach(feature => {
    console.log(feature.id, feature.geometry.type);
  });
});

Типы геометрий и влияние на события

Разные типы геометрий по-разному генерируют события:

Point

  • draw.create — мгновенное создание
  • draw.update — перемещение точки

LineString

  • draw.create — завершение линии
  • draw.update — изменение вершин

Polygon

  • draw.create — завершение замкнутой области
  • draw.update — редактирование контуров и дыр

Синхронизация с сервером в реальном времени

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

Пример архитектуры:

  • клиент генерирует события draw.*
  • сервер принимает GeoJSON изменения
  • другие клиенты получают обновления через WebSocket
map.on('draw.update', function (e) {
  socket.emit('feature:update', e.features);
});

map.on('draw.delete', function (e) {
  socket.emit('feature:delete', e.features);
});

Управление состоянием через id объектов

Каждый feature имеет уникальный id, который используется для:

  • сопоставления объектов между клиентом и сервером
  • обновления конкретных сущностей
  • удаления по идентификатору

Пример:

map.on('draw.update', function (e) {
  const feature = e.features[0];

  database.update(feature.id, feature);
});

Ошибки и особенности поведения событий

При работе с событиями важно учитывать следующие особенности:

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

Интеграция с пользовательским интерфейсом

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

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

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

map.on('draw.update', function (e) {
  updateSidebar(e.features);
});

map.on('draw.create', function (e) {
  addToList(e.features);
});

map.on('draw.delete', function (e) {
  removeFromList(e.features);
});

Поток данных между Mapbox GL JS и Draw

Mapbox GL JS отвечает за рендеринг, Mapbox GL Draw — за редактирование. События выступают мостом между визуальной частью и бизнес-логикой приложения.

  • GL JS отображает слой
  • Draw изменяет GeoJSON
  • события фиксируют изменения
  • приложение синхронизирует состояние

Так формируется замкнутый цикл управления геометрией на карте, где draw.create, draw.update, draw.delete являются основными точками контроля состояния.