Стилизация Draw

Стилизация инструментов рисования в Mapbox GL JS и плагине Mapbox GL Draw основана на переопределении набора слоёв (layers), которые отвечают за отображение геометрии в разных состояниях редактирования. В отличие от стандартных слоёв карты, Draw использует внутреннюю систему стилей, описываемую массивом объектов слоя, где каждый объект соответствует определённому состоянию feature.

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


Архитектура стилизации Draw

Система стилизации Mapbox Draw опирается на три уровня:

  • базовые слои карты (style layers)
  • слои пользовательских данных (GeoJSON layers)
  • слои Draw (внутренний набор styles)

Draw-слои добавляются поверх карты и управляют отображением:

  • точек (Point)
  • линий (LineString)
  • полигонов (Polygon)
  • вершин (vertices)
  • середины рёбер (midpoints)

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


Структура стиля Draw

Стиль описывается массивом объектов:

const draw = new MapboxDraw({
  styles: [
    {
      id: 'gl-draw-polygon-fill',
      type: 'fill',
      filter: ['all',
        ['==', '$type', 'Polygon'],
        ['!=', 'mode', 'static']
      ],
      paint: {
        'fill-color': '#3bb2d0',
        'fill-opacity': 0.4
      }
    }
  ]
});

Каждый объект содержит:

  • id — уникальное имя слоя
  • type — тип рендера (fill, line, circle)
  • filter — логика выбора feature
  • paint — визуальные параметры
  • layout — поведение слоя

Состояния геометрий

Draw использует внутренние состояния объектов:

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

  • active — объект редактируется
  • inactive — обычное состояние
  • selected — выделенный объект
  • static — неизменяемый объект

Технические состояния

  • вершины (vertices)
  • середины сегментов (midpoints)

Эти состояния позволяют строить интерфейс редактирования без DOM-слоёв, используя только WebGL рендеринг.


Стилизация полигонов

Полигон разбивается на два ключевых слоя:

1. Fill слой

{
  id: 'gl-draw-polygon-fill',
  type: 'fill',
  filter: ['all',
    ['==', '$type', 'Polygon'],
    ['!=', 'mode', 'static']
  ],
  paint: {
    'fill-color': [
      'case',
      ['boolean', ['feature-state', 'selected'], false],
      '#fbb03b',
      '#3bb2d0'
    ],
    'fill-opacity': 0.5
  }
}

2. Outline слой

{
  id: 'gl-draw-polygon-stroke',
  type: 'line',
  filter: ['all',
    ['==', '$type', 'Polygon']
  ],
  paint: {
    'line-color': '#000',
    'line-width': 2
  }
}

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


Стилизация линий (LineString)

Линии требуют отдельного контроля ширины и цвета:

{
  id: 'gl-draw-line',
  type: 'line',
  filter: ['all',
    ['==', '$type', 'LineString']
  ],
  paint: {
    'line-color': '#ff0000',
    'line-width': 3
  }
}

Динамическая толщина

Толщина может зависеть от состояния:

'line-width': [
  'case',
  ['boolean', ['feature-state', 'active'], false],
  5,
  2
]

Стилизация точек

Точки используются для:

  • одиночных маркеров
  • вершин редактирования
  • midpoint-узлов
{
  id: 'gl-draw-point',
  type: 'circle',
  filter: ['all',
    ['==', '$type', 'Point']
  ],
  paint: {
    'circle-radius': 6,
    'circle-color': '#ffcc00'
  }
}

Разделение точек по роли

Draw использует свойства:

  • meta: 'vertex'
  • meta: 'midpoint'
  • meta: 'feature'

Пример фильтра:

filter: ['all',
  ['==', 'meta', 'vertex']
]

Версионирование вершин (vertices)

Вершины — ключевой элемент UX редактирования.

{
  id: 'gl-draw-polygon-and-line-vertex',
  type: 'circle',
  filter: ['all',
    ['==', 'meta', 'vertex']
  ],
  paint: {
    'circle-radius': 4,
    'circle-color': '#ffffff',
    'circle-stroke-color': '#333',
    'circle-stroke-width': 2
  }
}

Особенность: вершины часто визуально отличаются от основной геометрии.


Midpoints (средние точки)

Midpoints позволяют добавлять новые узлы:

{
  id: 'gl-draw-polygon-midpoint',
  type: 'circle',
  filter: ['all',
    ['==', 'meta', 'midpoint']
  ],
  paint: {
    'circle-radius': 3,
    'circle-color': '#888'
  }
}

Они активируются только в режиме редактирования.


Feature-state как основа динамической стилизации

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

Пример:

map.setFeatureState(
  { source: 'mapbox-gl-draw', id: featureId },
  { active: true }
);

И использование в стиле:

'circle-color': [
  'case',
  ['boolean', ['feature-state', 'active'], false],
  '#f00',
  '#00f'
]

Полная кастомизация styles массива

Mapbox Draw позволяет полностью заменить стандартные стили:

const draw = new MapboxDraw({
  styles: customStylesArray
});

Это полностью отключает дефолтную визуальную модель.


Приоритет слоёв

Порядок в массиве styles определяет:

  • какой слой перекрывает другой
  • приоритет вершин над линиями
  • визуальную иерархию состояний

Типичная последовательность:

  1. fill
  2. line
  3. vertices
  4. midpoints

Интеграция с кастомными слоями карты

Слои Draw могут конфликтовать с пользовательскими слоями карты. Управление решается:

  • порядком map.addLayer
  • beforeId
  • разделением источников
map.addLayer(customLayer, 'gl-draw-polygon-fill');

Использование выражений (expressions)

Стили Draw активно используют expression API:

Интерполяция цвета

'fill-color': [
  'interpolate',
  ['linear'],
  ['zoom'],
  10, '#2DC4B2',
  15, '#3BB3C3'
]

Условные состояния

'circle-opacity': [
  'case',
  ['==', ['feature-state', 'selected'], true],
  1,
  0.5
]

Комбинирование режимов Draw и стилизации

Режимы редактирования влияют на стили:

  • draw_polygon
  • draw_line_string
  • draw_point
  • simple_select
  • direct_select

Фильтры часто используют mode:

filter: ['==', 'mode', 'simple_select']

Оптимизация рендера Draw-слоёв

Для сложных сцен важно:

  • минимизировать количество слоёв
  • избегать тяжёлых expressions на больших данных
  • разделять vertex и feature слои
  • использовать feature-state вместо перерисовки GeoJSON

Типичные паттерны кастомизации

Активный объект

  • увеличенный радиус
  • яркий цвет
  • увеличенная толщина линии

Неактивный объект

  • сниженная прозрачность
  • нейтральный цвет

Режим редактирования

  • отображение вершин
  • отображение midpoints
  • подсветка сегментов

Расширенная схема стилизации

Сложные редакторы часто строят 6–10 слоёв:

  • polygon fill (inactive)
  • polygon fill (active)
  • polygon stroke (inactive)
  • polygon stroke (active)
  • vertex points
  • midpoints
  • selected outline glow
  • hover highlight

Такая структура обеспечивает гибкость UX без изменения данных GeoJSON.