Загрузка GeoJSON

GeoJSON представляет собой текстовый формат для описания географических объектов в структуре JSON. Он поддерживает точки, линии, полигоны и их коллекции, а также расширенные свойства через поле properties.

В контексте веб-карт GeoJSON выступает универсальным слоем обмена данными между сервером и клиентом. При работе с картографическими библиотеками он чаще всего используется как промежуточный формат между хранилищем геоданных и визуальным отображением на карте.

Ключевые элементы структуры GeoJSON:

  • FeatureCollection — набор объектов
  • Feature — отдельный геообъект
  • geometry — геометрия (Point, LineString, Polygon и др.)
  • properties — пользовательские данные объекта

Особенность, которая критична при работе с картами: порядок координат строго определён как [долгота, широта], а не наоборот.


Интеграция GeoJSON в HERE Maps API

В экосистеме HERE Technologies работа с GeoJSON реализуется через набор классов карты и слоя данных. В JavaScript API используется объектная модель, где GeoJSON преобразуется в визуальные сущности карты.

Базовый подход включает три шага:

  1. Загрузка GeoJSON (локально или удалённо)
  2. Преобразование в объекты карты
  3. Добавление на слой отображения

Создание карты и подготовка слоя объектов

Перед загрузкой GeoJSON необходимо инициализировать карту и слой, в который будут добавляться геообъекты.

const platform = new H.service.Platform({
  apikey: 'YOUR_API_KEY'
});

const defaultLayers = platform.createDefaultLayers();

const map = new H.Map(
  document.getElementById('map'),
  defaultLayers.vector.normal.map,
  {
    center: { lat: 52.52, lng: 13.405 },
    zoom: 10,
    pixelRatio: window.devicePixelRatio || 1
  }
);

const beh * avior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
const ui = H.ui.UI.createDefault(map, defaultLayers);

После создания карты добавляется слой объектов:

const geoLayer = new H.map.Group();
map.addObject(geoLayer);

H.map.Group используется как контейнер для всех геообъектов, созданных из GeoJSON.


Загрузка GeoJSON из внешнего источника

Чаще всего GeoJSON хранится на сервере и загружается через fetch.

fetch('/data/objects.geojson')
  .then(response => response.json())
  .then(geojson => {
    addGeoJSONToMap(geojson);
  });

При загрузке важно учитывать:

  • CORS-политики сервера
  • размер файла
  • необходимость кэширования
  • валидацию структуры JSON

Преобразование GeoJSON в объекты HERE Maps

Основной процесс заключается в разборе FeatureCollection и создании соответствующих геометрических объектов.

function addGeoJSONToMap(geojson) {
  geojson.features.forEach(feature => {
    const geometry = feature.geometry;
    const properties = feature.properties;

    let mapObject = null;

    if (geometry.type === 'Point') {
      mapObject = createMarker(geometry.coordinates, properties);
    }

    if (geometry.type === 'LineString') {
      mapObject = createPolyline(geometry.coordinates, properties);
    }

    if (geometry.type === 'Polygon') {
      mapObject = createPolygon(geometry.coordinates, properties);
    }

    if (mapObject) {
      geoLayer.addObject(mapObject);
    }
  });
}

Работа с точками (Point)

Точечные объекты обычно отображаются маркерами.

function createMarker(coords, properties) {
  const [lng, lat] = coords;

  const marker = new H.map.Marker({ lat, lng });

  marker.setData(properties);

  return marker;
}

Метод setData позволяет привязать произвольные свойства GeoJSON к объекту карты.


Линии (LineString)

Линии преобразуются в H.map.Polyline.

function createPolyline(coords, properties) {
  const lineString = new H.geo.LineString();

  coords.forEach(c => {
    lineString.pushPoint({ lat: c[1], lng: c[0] });
  });

  const polyline = new H.map.Polyline(lineString, {
    style: {
      strokeColor: 'blue',
      lineWidth: 3
    }
  });

  polyline.setData(properties);

  return polyline;
}

Полигоны (Polygon)

Полигональные объекты требуют замыкания контура.

function createPolygon(coords, properties) {
  const exterior = coords[0];
  const lineString = new H.geo.LineString();

  exterior.forEach(c => {
    lineString.pushPoint({ lat: c[1], lng: c[0] });
  });

  const polygon = new H.map.Polygon(lineString, {
    style: {
      fillColor: 'rgba(255, 0, 0, 0.3)',
      strokeColor: 'red',
      lineWidth: 2
    }
  });

  polygon.setData(properties);

  return polygon;
}

Если GeoJSON содержит внутренние кольца (holes), они обрабатываются отдельно через дополнительные LineString.


Использование свойств объектов GeoJSON

Поле properties позволяет хранить метаданные:

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

Пример использования при клике:

map.addEventListener('tap', function (evt) {
  const target = evt.target;

  if (target instanceof H.map.Object && target.getData()) {
    const data = target.getData();
    console.log(data);
  }
});

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

Стили объектов можно изменять в зависимости от данных GeoJSON.

function createPolyline(coords, properties) {
  const lineString = new H.geo.LineString();

  coords.forEach(c => {
    lineString.pushPoint({ lat: c[1], lng: c[0] });
  });

  const color = properties.traffic === 'high' ? 'red' : 'green';

  return new H.map.Polyline(lineString, {
    style: {
      strokeColor: color,
      lineWidth: 4
    }
  });
}

Оптимизация загрузки больших GeoJSON

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

  • количество объектов на сцене
  • время парсинга JSON
  • нагрузка на DOM и WebGL слой

Практические подходы:

Фильтрация по области видимости

Загрузка данных только для текущего viewport:

map.getViewModel().addEventListener('sync', () => {
  const bounds = map.getViewModel().getLookAtData().bounds;
  loadGeoJSONForBounds(bounds);
});

Упрощение геометрии

Сложные полигоны стоит упрощать на сервере (например, алгоритмом Дугласа-Пекера), чтобы уменьшить количество точек.


Разбиение на тайлы

GeoJSON можно разбивать по тайловой сетке:

  • z/x/y структура
  • загрузка по мере необходимости
  • кэширование на клиенте

Альтернативный подход: Data Provider

В некоторых сценариях вместо ручного разбора GeoJSON используется H.data.geojson.Reader, который автоматически создаёт слой объектов.

const reader = new H.data.geojson.Reader('/data/objects.geojson');

reader.parse();

map.addLayer(reader.getLayer());

Такой подход упрощает код, но ограничивает гибкость кастомной обработки.


Обновление GeoJSON в реальном времени

При динамических данных требуется обновление слоя:

function refreshData(newGeoJSON) {
  geoLayer.removeAll();
  addGeoJSONToMap(newGeoJSON);
}

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


Обработка ошибок и валидация

Типичные проблемы:

  • некорректная структура FeatureCollection
  • отсутствующие координаты
  • перепутанный порядок lat/lng
  • несоответствие типов geometry

Базовая проверка:

function isValidFeature(feature) {
  return feature &&
         feature.geometry &&
         Array.isArray(feature.geometry.coordinates);
}

События и взаимодействие с GeoJSON-объектами

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

map.addEventListener('pointerenter', function (evt) {
  if (evt.target instanceof H.map.Polyline) {
    evt.target.setStyle({ strokeColor: 'orange' });
  }
});

Интерактивность GeoJSON часто строится вокруг событий hover и click, где свойства объекта используются для отображения информации или изменения визуального состояния.


Структурирование сложных наборов GeoJSON

При больших моделях данных применяется иерархия:

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

Пример разделения:

  • roads.geojson
  • buildings.geojson
  • points_of_interest.geojson

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