Подключение GeoJSON данных

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

Ключевые сущности GeoJSON:

  • Feature — объект, содержащий геометрию и набор свойств
  • FeatureCollection — коллекция объектов Feature
  • Geometry — геометрическое описание (Polygon, MultiPolygon, Point и др.)

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

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": "region-1",
      "properties": {
        "name": "Region A"
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [50, 10],
            [51, 10],
            [51, 11],
            [50, 11],
            [50, 10]
          ]
        ]
      }
    }
  ]
}

Для библиотек визуализации, включая Nivo, критическим элементом становится поле id, которое используется для сопоставления геометрии с пользовательскими данными.


Подключение GeoJSON в Nivo Geo-компоненты

Библиотека Nivo предоставляет пакет @nivo/geo, предназначенный для работы с картографическими данными. Основной компонент — ResponsiveChoropleth или ResponsiveGeoMap.

GeoJSON передаётся через свойство features, а отображаемые данные — через массив значений.

import { ResponsiveChoropleth } from '@nivo/geo'
import worldCountries from './world_countries.json'

const data = [
  { id: 'USA', value: 342 },
  { id: 'FRA', value: 128 },
  { id: 'RUS', value: 412 }
]

const GeoChart = () => (
  <ResponsiveChoropleth
    data={data}
    features={worldCountries.features}
    margin={{ top: 0, right: 0, bottom: 0, left: 0 }}
    colors="nivo"
    domain={[0, 500]}
    unknownColor="#666666"
    label="properties.name"
    valueFormat=".0f"
    projectionScale={140}
    projectionTranslation={[0.5, 0.5]}
    projectionRotation={[0, 0, 0]}
  />
)

В этом примере GeoJSON выступает как геометрический слой, а данные массива — как слой значений.


Механизм сопоставления данных с геометрией

Основной принцип работы Nivo Geo заключается в связывании data.id с feature.id. Это ключевой момент, от которого зависит корректность визуализации.

Алгоритм сопоставления:

  1. Из GeoJSON извлекается массив features
  2. Для каждого элемента берётся feature.id
  3. Выполняется поиск объекта в data с совпадающим id
  4. Значение value применяется к геометрии

Если совпадение отсутствует, используется цвет unknownColor.

Пример несоответствия:

const data = [
  { id: 'US', value: 100 }
]

const feature = {
  id: 'USA'
}

В данном случае визуализация не отобразит значение, поскольку идентификаторы различаются.


Нормализация идентификаторов

GeoJSON-файлы разных источников используют различные схемы идентификации: ISO-коды, числовые ID, строковые названия.

Для корректной работы с Nivo требуется привести данные к единому формату.

Пример нормализации:

const normalizeData = (raw) =>
  raw.map(item => ({
    id: item.country_code.toUpperCase(),
    value: item.metric
  }))

И аналогично может потребоваться трансформация GeoJSON:

const normalizedFeatures = geo.features.map(f => ({
  ...f,
  id: f.properties.ISO_A3
}))

Использование проекций и географической трансформации

Nivo использует d3-geo под капотом, что позволяет применять различные картографические проекции.

Основные параметры:

  • projectionScale — масштаб карты
  • projectionTranslation — смещение центра
  • projectionRotation — поворот координат

Пример настройки:

<ResponsiveChoropleth
  projectionScale={150}
  projectionTranslation={[0.5, 0.5]}
  projectionRotation={[0, 0, 0]}
/>

Изменение этих параметров напрямую влияет на визуальную читаемость карты и распределение регионов.


Работа с пользовательскими GeoJSON слоями

Помимо стандартных карт мира, возможно использование кастомных GeoJSON файлов: регионов стран, городских границ, административных делений.

Пример загрузки локального GeoJSON:

import regions from './regions.geojson'

const Map = () => (
  <ResponsiveGeoMap
    features={regions.features}
    fillColor="#eeeeee"
    borderColor="#333333"
  />
)

В таких случаях особое значение приобретает корректность топологии и отсутствие пересечений в полигонах.


Стилизация географических объектов

Стилизация в Nivo осуществляется через набор параметров, влияющих на отображение областей:

  • colors — шкала цветов (sequential, diverging, categorical)
  • domain — диапазон значений
  • unknownColor — цвет отсутствующих данных
  • borderColor — цвет границ
  • borderWidth — толщина линий

Пример цветовой шкалы:

colors={{ scheme: 'blues' }}

Или ручная настройка:

colors={value =>
  value > 300 ? '#08306b' :
  value > 100 ? '#4292c6' :
  '#c6dbef'
}

Поддержка интерактивности

Geo-компоненты Nivo поддерживают события наведения и кликов по регионам.

onCl ick={(feature) => {
  console.log(feature.id)
}}

onMouseEn ter={(feature) => {
  console.log(feature.properties.name)
}}

События позволяют связывать карту с внешними компонентами интерфейса, такими как таблицы или графики.


Обработка отсутствующих и некорректных данных

При работе с GeoJSON часто встречаются ситуации неполного покрытия данных.

Основные сценарии:

  • отсутствует feature.id
  • отсутствует соответствие в data
  • значение value = null

Стратегии обработки:

unknownColor="#444444"

или предварительная фильтрация:

const cleanedData = data.filter(d => d.value != null)

Также возможно задание дефолтного значения:

const safeData = data.map(d => ({
  ...d,
  value: d.value ?? 0
}))

Оптимизация производительности при больших GeoJSON

При работе с высокодетализированными картами (например, административные уровни городов) возникают проблемы производительности.

Основные методы оптимизации:

  • упрощение геометрии (simplification)
  • уменьшение количества вершин в полигонах
  • кеширование подготовленных GeoJSON
  • использование React.memo для компонента карты

Пример упрощения данных до загрузки:

import simplify from 'simplify-geojson'

const simplified = simplify(geojson, 0.01)

Дополнительно можно разделять карту на слои и подгружать их асинхронно.


Координация GeoJSON с бизнес-данными

В реальных сценариях GeoJSON редко используется изолированно. Чаще он объединяется с аналитическими данными: демография, экономика, логистика.

Структура объединения:

const merged = geo.features.map(feature => ({
  ...feature,
  value: metrics[feature.id]
}))

При этом GeoJSON остаётся неизменяемым слоем геометрии, а данные накладываются поверх него логически.


Использование кастомных tooltip на Geo-слое

Tooltip в Nivo позволяет отображать расширенную информацию при наведении:

tooltip={({ feature }) => (
  <div>
    <strong>{feature.properties.name}</strong>
    <div>{feature.value}</div>
  </div>
)}

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


Работа с различными типами геометрии

GeoJSON поддерживает несколько типов геометрии, однако Nivo Geo в основном ориентирован на:

  • Polygon
  • MultiPolygon

Point-объекты используются ограниченно и чаще требуют кастомной обработки.

Структуры MultiPolygon применяются для стран с островными территориями или сложной границей:

{
  "type": "MultiPolygon",
  "coordinates": [
    [[[0,0],[1,0],[1,1],[0,1],[0,0]]],
    [[[2,2],[3,2],[3,3],[2,3],[2,2]]]
  ]
}

Согласование системы координат

GeoJSON использует стандарт WGS84 (EPSG:4326). Это означает:

  • долгота и широта
  • порядок координат [lng, lat]

Ошибка в порядке координат приводит к искажению карты:

// корректно
[longitude, latitude]

// некорректно
[latitude, longitude]

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


Интеграция с серверной подготовкой данных

В высоконагруженных системах GeoJSON часто подготавливается на сервере.

Сценарии серверной обработки:

  • агрегация статистики по регионам
  • объединение нескольких источников данных
  • генерация упрощённых версий геометрии

Пример серверного JSON:

{
  "id": "DEU",
  "value": 230,
  "geometry": { }
}

Клиентская часть Nivo затем использует только финальную структуру без дополнительной трансформации.