Point геометрия

Точечная геометрия в MapLibre GL JS основана на стандарте GeoJSON, где тип Point описывает одиночную координату в географическом пространстве. Структура объекта минимальна и строго формализована:

{
  "type": "Point",
  "coordinates": [lng, lat]
}

Ключевой особенностью является порядок координат: сначала долгота, затем широта. Это соответствует спецификации GeoJSON и отличается от многих GIS-систем, где используется обратный порядок.

Точечные объекты применяются для представления:

  • маркеров объектов на карте;
  • пользовательских событий и местоположений;
  • точек интереса (POI);
  • центров кластеров;
  • результатов геокодинга.

Источники данных и добавление Point в карту

В MapLibre GL JS точечные данные передаются через источник типа geojson. Структура слоя начинается с описания источника:

map.addSource('points-source', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [37.6173, 55.7558]
        },
        properties: {
          title: 'Москва'
        }
      }
    ]
  }
});

Источник может быть динамическим. Обновление данных выполняется через setData, что позволяет изменять точечные объекты без пересоздания слоя:

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

Визуализация Point через слои

Точечные данные не отображаются напрямую. Для их визуализации используются слои (layers), чаще всего типов circle и symbol.

Circle layer

circle слой отображает точку как геометрический круг в экранных координатах:

map.addLayer({
  id: 'points-circle',
  type: 'circle',
  source: 'points-source',
  paint: {
    'circle-radius': 6,
    'circle-color': '#3b82f6',
    'circle-stroke-width': 2,
    'circle-stroke-color': '#ffffff'
  }
});

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

Symbol layer

symbol слой используется для отображения точек как иконок и текстов:

map.addLayer({
  id: 'points-symbol',
  type: 'symbol',
  source: 'points-source',
  layout: {
    'icon-image': 'marker-15',
    'text-field': ['get', 'title'],
    'text-offset': [0, 1.2],
    'text-anchor': 'top'
  }
});

Symbol слой поддерживает:

  • динамические выражения (get, match, case);
  • масштабирование текста и иконок;
  • управление перекрытиями (text-allow-overlap, icon-allow-overlap).

Координатная система и проекция

MapLibre GL JS использует Web Mercator (EPSG:3857). Это означает, что географические координаты преобразуются в плоскую карту с искажениями на полюсах.

При работе с Point важно учитывать:

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

Преобразование координат можно выполнять через API карты:

const pixel = map.project([37.6173, 55.7558]);
const lngLat = map.unproject([100, 200]);

Интерактивность точечных объектов

Point-геометрия часто используется вместе с обработчиками событий. MapLibre предоставляет механизм определения объектов под курсором:

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

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

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

События доступны для слоёв:

  • click
  • mouseenter
  • mouseleave
  • mousemove

Это позволяет реализовывать интерактивные маркеры и всплывающие окна.

Динамическое стилизование точек

Стилизация точек часто зависит от свойств объекта. MapLibre GL JS использует выражения style specification:

'circle-color': [
  'match',
  ['get', 'type'],
  'city', '#f97316',
  'village', '#22c55e',
  '#3b82f6'
]

Размер точки может зависеть от масштаба:

'circle-radius': [
  'interpolate',
  ['linear'],
  ['zoom'],
  5, 2,
  10, 6,
  15, 12
]

Такая привязка обеспечивает адаптивную визуализацию при изменении zoom.

Кластеризация точек

При работе с большим количеством Point-объектов используется кластеризация:

map.addSource('points-source', {
  type: 'geojson',
  data: geojson,
  cluster: true,
  clusterMaxZoom: 14,
  clusterRadius: 50
});

Кластеры представляют собой агрегированные точки, заменяющие плотные группы объектов.

Отдельный слой отображает кластеры:

map.addLayer({
  id: 'clusters',
  type: 'circle',
  source: 'points-source',
  filter: ['has', 'point_count'],
  paint: {
    'circle-radius': 15,
    'circle-color': '#6366f1'
  }
});

И слой для одиночных точек:

map.addLayer({
  id: 'unclustered-point',
  type: 'circle',
  source: 'points-source',
  filter: ['!', ['has', 'point_count']],
  paint: {
    'circle-radius': 5,
    'circle-color': '#ef4444'
  }
});

Производительность точечных данных

Обработка Point-объектов в MapLibre оптимизирована под WebGL. Однако при большом количестве данных возникают ограничения:

  • десятки тысяч точек требуют кластеризации;
  • сложные выражения увеличивают нагрузку на GPU;
  • частые вызовы setData влияют на производительность.

Оптимизационные подходы включают:

  • упрощение GeoJSON;
  • использование векторных тайлов вместо GeoJSON;
  • минимизацию свойств properties;
  • ограничение количества активных слоёв.

Работа с экранными координатами

Point-геометрия существует в географическом пространстве, но отображается в экранных координатах. MapLibre выполняет трансформацию автоматически.

Для задач UI часто требуется привязка к пикселям:

const coordinates = [37.6173, 55.7558];
const point = map.project(coordinates);

const offsetX = point.x + 10;
const offsetY = point.y + 10;

Это используется для:

  • кастомных попапов;
  • HTML-оверлеев;
  • синхронизации DOM-элементов с картой.

Использование фильтров для Point

Фильтры позволяют управлять видимостью точек:

filter: ['==', ['get', 'category'], 'restaurant']

Комбинации условий:

filter: [
  'all',
  ['==', ['get', 'type'], 'city'],
  ['>=', ['get', 'population'], 100000]
]

Фильтрация выполняется на уровне рендеринга WebGL, что обеспечивает высокую скорость даже при больших наборах данных.

Событийная модель и hit detection

MapLibre GL JS использует механизм определения попадания курсора в геометрию слоя. Для Point-объектов это особенно эффективно, так как проверяется расстояние до пиксельного центра.

При обработке событий:

  • учитывается радиус circle-radius;
  • учитывается размер иконки в symbol;
  • применяется порядок слоёв (z-index через порядок добавления).

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