GeoJSON представляет собой текстовый формат для описания
географических объектов в структуре JSON. Он поддерживает точки, линии,
полигоны и их коллекции, а также расширенные свойства через поле
properties.
В контексте веб-карт GeoJSON выступает универсальным слоем обмена данными между сервером и клиентом. При работе с картографическими библиотеками он чаще всего используется как промежуточный формат между хранилищем геоданных и визуальным отображением на карте.
Ключевые элементы структуры GeoJSON:
FeatureCollection — набор объектовFeature — отдельный геообъектgeometry — геометрия (Point, LineString, Polygon и
др.)properties — пользовательские данные объектаОсобенность, которая критична при работе с картами: порядок координат строго определён как [долгота, широта], а не наоборот.
В экосистеме HERE Technologies работа с GeoJSON реализуется через набор классов карты и слоя данных. В JavaScript API используется объектная модель, где GeoJSON преобразуется в визуальные сущности карты.
Базовый подход включает три шага:
Перед загрузкой 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 хранится на сервере и загружается через
fetch.
fetch('/data/objects.geojson')
.then(response => response.json())
.then(geojson => {
addGeoJSONToMap(geojson);
});
При загрузке важно учитывать:
Основной процесс заключается в разборе 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);
}
});
}
Точечные объекты обычно отображаются маркерами.
function createMarker(coords, properties) {
const [lng, lat] = coords;
const marker = new H.map.Marker({ lat, lng });
marker.setData(properties);
return marker;
}
Метод setData позволяет привязать произвольные свойства
GeoJSON к объекту карты.
Линии преобразуются в 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;
}
Полигональные объекты требуют замыкания контура.
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.
Поле 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
}
});
}
При работе с большими наборами данных возникают ограничения производительности:
Практические подходы:
Загрузка данных только для текущего viewport:
map.getViewModel().addEventListener('sync', () => {
const bounds = map.getViewModel().getLookAtData().bounds;
loadGeoJSONForBounds(bounds);
});
Сложные полигоны стоит упрощать на сервере (например, алгоритмом Дугласа-Пекера), чтобы уменьшить количество точек.
GeoJSON можно разбивать по тайловой сетке:
В некоторых сценариях вместо ручного разбора GeoJSON используется
H.data.geojson.Reader, который автоматически создаёт слой
объектов.
const reader = new H.data.geojson.Reader('/data/objects.geojson');
reader.parse();
map.addLayer(reader.getLayer());
Такой подход упрощает код, но ограничивает гибкость кастомной обработки.
При динамических данных требуется обновление слоя:
function refreshData(newGeoJSON) {
geoLayer.removeAll();
addGeoJSONToMap(newGeoJSON);
}
Для потоковых данных часто используется стратегия частичного обновления, когда изменяются только затронутые объекты, а не весь слой.
Типичные проблемы:
Базовая проверка:
function isValidFeature(feature) {
return feature &&
feature.geometry &&
Array.isArray(feature.geometry.coordinates);
}
Каждый объект карты может реагировать на события:
map.addEventListener('pointerenter', function (evt) {
if (evt.target instanceof H.map.Polyline) {
evt.target.setStyle({ strokeColor: 'orange' });
}
});
Интерактивность GeoJSON часто строится вокруг событий hover и click, где свойства объекта используются для отображения информации или изменения визуального состояния.
При больших моделях данных применяется иерархия:
Пример разделения:
Каждый файл обрабатывается отдельно и добавляется в карту как независимый слой.