Загрузка GeoJSON

GeoJSON представляет собой стандарт обмена географическими данными, основанный на JSON. В Google Maps JavaScript API он используется через слой данных (Data Layer), который обеспечивает загрузку, отображение и управление геометриями без необходимости вручную создавать маркеры, полигоны или линии.

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


Структура GeoJSON и требования API

Google Maps API поддерживает стандарт RFC 7946, в котором координаты задаются в формате [долгота, широта], что критично при работе с данными:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [76.9457, 43.2565]
      },
      "properties": {
        "name": "Объект"
      }
    }
  ]
}

Ключевые элементы:

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

Загрузка GeoJSON через Data Layer

Основной способ интеграции — использование метода loadGeoJson объекта map.data.

const map = new google.maps.Map(document.getElementById("map"), {
  center: { lat: 43.2565, lng: 76.9457 },
  zoom: 10
});

map.data.loadGeoJson("data/objects.json");

Метод выполняет HTTP-запрос, загружает файл и автоматически добавляет все объекты в слой данных карты.

Особенности поведения:

  • загрузка асинхронная
  • поддерживаются локальные и удалённые URL
  • применяется стандартная обработка GeoJSON без дополнительного парсинга
  • объекты сразу становятся интерактивными элементами карты

Добавление GeoJSON из объекта JavaScript

При наличии уже загруженного JSON-объекта используется addGeoJson:

fetch("data/objects.json")
  .then(response => response.json())
  .then(data => {
    map.data.addGeoJson(data);
  });

Отличие от loadGeoJson:

  • отсутствует встроенный HTTP-запрос
  • данные могут быть модифицированы перед добавлением
  • подходит для API-агрегации и динамической генерации

Управление стилями GeoJSON-слоя

После загрузки все элементы отображаются с базовым стилем Google Maps. Управление визуализацией осуществляется через setStyle:

map.data.setStyle(feature => {
  return {
    fillColor: "#2E7D32",
    fillOpacity: 0.4,
    strokeColor: "#1B5E20",
    strokeWeight: 2,
    icon: {
      path: google.maps.SymbolPath.CIRCLE,
      scale: 6
    }
  };
});

Возможности стилизации:

  • динамическое изменение по properties
  • условное форматирование
  • разные стили для точек, линий и полигонов
  • использование SVG-символов

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

map.data.setStyle(feature => {
  const type = feature.getProperty("type");

  return {
    fillColor: type === "park" ? "green" : "gray",
    strokeWeight: 1
  };
});

Обработка событий GeoJSON-объектов

Data Layer поддерживает событийную модель:

map.data.addListener("click", event => {
  const name = event.feature.getProperty("name");
  console.log(name);
});

Основные события:

  • click — взаимодействие с объектом
  • mouseover — наведение
  • mouseout — уход курсора
  • addfeature — добавление объекта
  • removefeature — удаление объекта

Объект события содержит:

  • feature — GeoJSON Feature
  • геометрические данные
  • свойства properties

Центрирование карты по GeoJSON данным

После загрузки часто требуется вычислить границы всех объектов:

const bounds = new google.maps.LatLngBounds();

map.data.forEach(feature => {
  feature.getGeometry().forEachLatLng(latlng => {
    bounds.extend(latlng);
  });
});

map.fitBounds(bounds);

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


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

Data Layer поддерживает изменение данных без перезагрузки карты:

map.data.add({ 
  geometry: new google.maps.Data.Point({ lat: 43.25, lng: 76.95 }),
  properties: { name: "Новый объект" }
});

Удаление объектов:

map.data.forEach(feature => {
  if (feature.getProperty("id") === 10) {
    map.data.remove(feature);
  }
});

Обновление свойств:

feature.setProperty("status", "active");

Работа с удалёнными GeoJSON-файлами и CORS

При загрузке через loadGeoJson действует стандартная политика CORS браузера.

Типовые ограничения:

  • сервер должен отдавать заголовок Access-Control-Allow-Origin
  • HTTPS обязателен при использовании защищённого контекста страницы
  • локальные файлы через file:// могут блокироваться

Пример корректного запроса:

map.data.loadGeoJson("https://example.com/geo/data.json");

Фильтрация объектов GeoJSON

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

map.data.setStyle(feature => {
  return {
    visible: feature.getProperty("active") === true
  };
});

Также можно использовать глобальную фильтрацию:

map.data.revertStyle();

Преобразование GeoJSON перед загрузкой

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

fetch("data.json")
  .then(res => res.json())
  .then(data => {
    data.features = data.features.filter(f => f.geometry);

    data.features.forEach(f => {
      f.properties.timestamp = Date.now();
    });

    map.data.addGeoJson(data);
  });

Типовые операции:

  • фильтрация некорректных объектов
  • добавление вычисляемых свойств
  • изменение структуры properties

Производительность при работе с большими GeoJSON

При работе с тысячами объектов критично учитывать нагрузку Data Layer:

  • большое число Polygon снижает FPS
  • сложные геометрии требуют упрощения
  • предпочтительно использовать кластеризацию для Point-данных
  • загрузку следует разбивать на регионы

Оптимизация через разделение данных:

["region1.json", "region2.json"].forEach(url => {
  map.data.loadGeoJson(url);
});

Геометрические типы и их особенности

Поддерживаемые типы GeoJSON:

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

Пример полигона:

{
  "type": "Polygon",
  "coordinates": [
    [
      [76.9, 43.2],
      [77.0, 43.2],
      [77.0, 43.3],
      [76.9, 43.3],
      [76.9, 43.2]
    ]
  ]
}

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

GeoJSON часто выступает промежуточным форматом между backend и картой:

async function loadFromAPI() {
  const response = await fetch("/api/objects");
  const geojson = await response.json();

  map.data.addGeoJson(geojson);
}

Серверные системы обычно формируют FeatureCollection на основе:

  • PostgreSQL/PostGIS
  • MongoDB geospatial queries
  • GIS-систем (QGIS, ArcGIS)
  • кастомных сервисов геоаналитики

Сброс и переинициализация слоя данных

Полная очистка Data Layer выполняется через удаление всех features:

map.data.forEach(feature => {
  map.data.remove(feature);
});

После этого слой готов к новой загрузке GeoJSON без перезагрузки карты.