Feature и FeatureCollection

GeoJSON Feature — базовая единица данных, используемая в веб-картографии и являющаяся фундаментом для работы с векторными слоями в MapLibre GL JS. В рамках спецификации GeoJSON каждый объект карты представляется как отдельная сущность с геометрией и набором свойств, которые могут быть интерпретированы стилями слоёв, фильтрами и интерактивными обработчиками.

Feature представляет собой объект, который объединяет геометрические данные и атрибутивную информацию. В MapLibre GL JS он используется для описания конкретных объектов на карте: точек, линий, полигонов и их вариаций.

Базовая структура Feature:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [30.31413, 59.93863]
  },
  "properties": {
    "name": "Объект",
    "category": "example"
  }
}

Геометрия Feature

Поле geometry определяет пространственную форму объекта. Поддерживаются основные типы:

  • Point — точечные объекты (метки, маркеры)
  • LineString — линии (маршруты, дороги)
  • Polygon — полигоны (зоны, здания, территории)
  • MultiPoint, MultiLineString, MultiPolygon — множественные геометрии

Геометрия является обязательной частью Feature, за исключением случая null, который используется для временно отсутствующих или скрытых объектов.

Properties как источник семантики

Поле properties содержит произвольные данные, которые не влияют на геометрию, но активно используются в визуализации и логике:

{
  "properties": {
    "id": 42,
    "name": "Парк",
    "population": 12000,
    "visible": true
  }
}

В MapLibre GL JS эти данные применяются:

  • в выражениях стилей (paint/layout properties)
  • в фильтрах слоёв
  • в обработке событий (click, hover)
  • при динамическом обновлении состояния объектов

FeatureCollection как контейнер данных

FeatureCollection — это контейнер, объединяющий множество Feature в единый объект GeoJSON. Он является основным форматом передачи данных в источники MapLibre.

Структура:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [30.1, 59.9]
      },
      "properties": {
        "id": 1,
        "label": "A"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [30.2, 59.8]
      },
      "properties": {
        "id": 2,
        "label": "B"
      }
    }
  ]
}

FeatureCollection используется как основной формат для GeoJSONSource, обеспечивая динамическое обновление данных на карте.

Использование FeatureCollection в источниках MapLibre

GeoJSON источник подключается через addSource:

map.addSource('points-source', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: []
  }
});

Обновление данных выполняется через setData:

map.getSource('points-source').setData(featureCollection);

Это позволяет динамически изменять отображаемые объекты без пересоздания слоя.

Связь Feature и слоёв (layers)

Feature напрямую не отображается на карте — он становится видимым только через слой (layer). Слой определяет:

  • тип визуализации (circle, line, fill, symbol)
  • стилизацию
  • фильтрацию по properties
  • поведение при масштабировании

Пример слоя:

map.addLayer({
  id: 'points-layer',
  type: 'circle',
  source: 'points-source',
  paint: {
    'circle-radius': 6,
    'circle-color': '#ff0000'
  }
});

Каждый Feature в FeatureCollection проходит через слой и отображается согласно его стилю.

Фильтрация Feature через properties

Одной из ключевых возможностей является фильтрация объектов на основе их свойств:

map.addLayer({
  id: 'filtered-layer',
  type: 'circle',
  source: 'points-source',
  filter: ['==', ['get', 'category'], 'park'],
  paint: {
    'circle-color': '#00aa00'
  }
});

Фильтры позволяют выделять подмножества Feature без изменения исходного источника данных.

FeatureState и динамическое состояние объектов

MapLibre GL JS предоставляет механизм feature-state, позволяющий хранить временное состояние объекта независимо от GeoJSON:

map.setFeatureState(
  { source: 'points-source', id: 1 },
  { hover: true }
);

В стилях это состояние используется через выражения:

'circle-color': [
  'case',
  ['boolean', ['feature-state', 'hover'], false],
  '#ff0000',
  '#0000ff'
]

FeatureState применяется для интерактивных сценариев:

  • hover-эффекты
  • выделение выбранных объектов
  • анимация состояния

Идентификация Feature и поле id

Для работы с состояниями и обновлениями каждому Feature может быть назначено уникальное поле id:

{
  "type": "Feature",
  "id": 10,
  "geometry": {
    "type": "Point",
    "coordinates": [30, 60]
  },
  "properties": {}
}

Наличие id позволяет:

  • быстро обновлять конкретный объект
  • использовать feature-state
  • оптимизировать взаимодействие с большими наборами данных

Динамическое обновление FeatureCollection

GeoJSON источник в MapLibre не является иммутабельным. Полная замена данных происходит через setData, что требует передачи новой FeatureCollection:

const updated = {
  type: 'FeatureCollection',
  features: [
    ...oldFeatures,
    newFeature
  ]
};

source.setData(updated);

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

Query API и извлечение Feature с карты

MapLibre GL JS позволяет извлекать Feature, уже отрендеренные на карте:

const features = map.queryRenderedFeatures(point, {
  layers: ['points-layer']
});

или по геометрической области:

const features = map.queryRenderedFeatures(bbox, {
  layers: ['points-layer']
});

Результатом являются объекты Feature, обогащённые информацией о визуализации.

Взаимодействие Feature с событиями

Feature активно участвует в обработке событий карты:

map.on('click', 'points-layer', (e) => {
  const feature = e.features[0];
  console.log(feature.properties);
});

Каждое событие передаёт массив Feature, соответствующих точке взаимодействия.

Вложенные свойства и выражения

Properties Feature могут использоваться в сложных выражениях стиля:

'circle-radius': [
  'interpolate',
  ['linear'],
  ['get', 'population'],
  0, 4,
  1000, 8,
  10000, 16
]

Это позволяет строить визуализации, зависящие от атрибутивных данных.

Особенности работы с большими FeatureCollection

При работе с тысячами и миллионами Feature критичны:

  • минимизация размера properties
  • использование кластеризации
  • предагрегация данных
  • оптимизация геометрии

Кластеризация:

map.addSource('points', {
  type: 'geojson',
  data: featureCollection,
  cluster: true,
  clusterRadius: 50
});

Feature в этом случае объединяются в агрегированные объекты.

Геометрическая точность и порядок координат

GeoJSON строго определяет порядок координат:

  • сначала долгота
  • затем широта
"coordinates": [longitude, latitude]

Нарушение порядка приводит к некорректному отображению Feature на карте.

Роль Feature в архитектуре MapLibre GL JS

Feature является связующим звеном между:

  • источниками данных (sources)
  • визуализацией (layers)
  • взаимодействием (events)
  • состоянием (feature-state)

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