TopoJSON представляет собой расширение идеи GeoJSON, в котором геометрии хранятся не как независимые наборы координат, а как топологически связанные структуры. Основное отличие заключается в том, что общие границы объектов не дублируются, а выносятся в отдельные арки (arcs), которые переиспользуются между геометриями.
В традиционном GeoJSON каждая геометрия содержит полный набор координат. Это приводит к избыточности при наличии смежных полигонов. TopoJSON устраняет это за счёт введения следующих концепций:
Ключевым результатом такого подхода становится значительное уменьшение размера данных при работе с административными границами, странами, регионами и другими полигонами с общей геометрией.
Использование TopoJSON особенно эффективно в задачах, где важны:
Сжатие достигается не только за счёт устранения повторяющихся координат, но и благодаря квантованию координат, которое позволяет хранить данные с фиксированной точностью.
В контексте веб-картографических библиотек, таких как OpenLayers, это напрямую влияет на производительность отрисовки и время первичной загрузки слоёв.
OpenLayers предоставляет встроенную поддержку формата TopoJSON через класс форматирования:
import TopoJSON from 'ol/format/TopoJSON';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
Основной механизм работы заключается в преобразовании топологических
структур в набор объектов ol.Feature, которые затем
отображаются как обычные векторные геометрии.
Типичная схема подключения TopoJSON в OpenLayers строится через
VectorSource, где формат данных указывается явно:
import Map from 'ol/Map';
import View from 'ol/View';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import TopoJSON from 'ol/format/TopoJSON';
import { fromLonLat } from 'ol/proj';
const vectorSource = new VectorSource({
url: 'data/countries.topojson',
format: new TopoJSON({
layers: ['countries']
})
});
const vectorLayer = new VectorLayer({
source: vectorSource
});
const map = new Map({
target: 'map',
layers: [vectorLayer],
view: new View({
center: fromLonLat([0, 20]),
zoom: 2
})
});
В этом примере ключевым параметром является layers,
который определяет, какие объекты внутри TopoJSON должны быть
извлечены.
TopoJSON-файл обычно содержит несколько логических объектов. Пример структуры:
{
"type": "Topology",
"objects": {
"countries": {
"type": "GeometryCollection",
"geometries": [
{ "type": "Polygon", "arcs": [[0]] },
{ "type": "Polygon", "arcs": [[1]] }
]
}
},
"arcs": [
[[0,0],[10,0],[10,10],[0,10],[0,0]],
[[10,10],[20,10],[20,20],[10,20],[10,10]]
],
"transform": {
"scale": [0.1, 0.1],
"translate": [0, 0]
}
}
OpenLayers интерпретирует эту структуру следующим образом:
objects определяет логические группы геометрийgeometries содержит ссылки на arcsarcs хранит координатные сегментыtransform применяется для восстановления реальных
координатTopoJSON использует механизм квантования координат. Реальные координаты восстанавливаются по формуле:
x = x_{quantized} scale_x + translate_x
y = y_{quantized} scale_y + translate_y
Этот процесс выполняется внутри парсера формата OpenLayers, поэтому разработчик обычно не работает с ним напрямую. Однако понимание механизма важно для оценки точности данных и возможных искажений при сильной генерализации.
TopoJSON может содержать несколько независимых наборов объектов. В
OpenLayers это управляется через параметр layers.
const source = new VectorSource({
url: 'data/world.topojson',
format: new TopoJSON({
layers: ['countries', 'rivers', 'cities']
})
});
Каждый слой извлекается как отдельная коллекция Feature.
Это позволяет комбинировать разные типы геометрий в одном файле без
дополнительных HTTP-запросов.
OpenLayers автоматически преобразует координаты в систему проекции карты, однако при необходимости можно явно задать входную и выходную проекции:
const format = new TopoJSON({
layers: ['countries'],
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
});
dataProjection соответствует системе координат
исходного TopoJSONfeatureProjection определяет систему координат
картыЧаще всего TopoJSON хранится в WGS84 (EPSG:4326), а
карта отображается в Web Mercator (EPSG:3857).
После преобразования данных в ol.Feature применяется
стандартная система стилизации OpenLayers.
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
const style = new Style({
fill: new Fill({
color: 'rgba(0, 150, 200, 0.3)'
}),
stroke: new Stroke({
color: '#3399CC',
width: 1
})
});
const vectorLayer = new VectorLayer({
source: vectorSource,
style: style
});
Стили применяются независимо от того, был ли исходный формат GeoJSON или TopoJSON — после парсинга различий на уровне отображения уже нет.
При работе с крупными наборами данных ключевыми становятся следующие подходы:
1. Предварительная генерализация TopoJSON часто создаётся с разным уровнем детализации. Уменьшение количества координат снижает нагрузку на рендеринг.
2. Разделение по слоям Разбиение данных на тематические файлы позволяет загружать только необходимые части.
3. Использование кеширования Поскольку TopoJSON обычно статичен, эффективное HTTP-кеширование существенно снижает повторные загрузки.
4. Снижение точности transform Параметры
scale и translate влияют на компромисс между
точностью и размером.
Наиболее распространённый инструмент для преобразования GeoJSON в TopoJSON — утилиты экосистемы TopoJSON:
topojson-servermapshaperПример CLI-конвертации:
mapshaper input.geojson -o format=topojson output.topojson
При генерации часто выполняется:
TopoJSON может использоваться не только как статический файл, но и как часть динамического API-ответа. В этом случае OpenLayers работает с URL-источником аналогично другим форматам:
const dynamicSource = new VectorSource({
loader: function (extent, resolution, projection) {
fetch('/api/regions.topojson')
.then(response => response.json())
.then(data => {
const format = new TopoJSON({ layers: ['regions'] });
const features = format.readFeatures(data, {
featureProjection: projection
});
dynamicSource.addFeatures(features);
});
}
});
Такой подход используется в системах, где геоданные формируются на сервере в реальном времени.
При работе с TopoJSON в OpenLayers возможны типичные проблемы:
layersobjectsВ таких случаях парсер может возвращать пустые наборы
Feature, не прерывая выполнение программы, что требует
дополнительной диагностики на уровне данных.
После декодирования TopoJSON превращается в стандартные векторные объекты, поэтому основная экономия достигается до этапа рендеринга:
При большом количестве смежных полигонов эффект становится особенно заметным, так как исключается повторная обработка общих границ.
OpenLayers позволяет использовать несколько источников данных одновременно. TopoJSON часто комбинируется с:
const map = new Map({
layers: [
rasterLayer,
vectorTopoLayer,
vectorGeoJsonLayer
],
target: 'map'
});
Такая архитектура позволяет разделять статические административные данные и динамические объекты.
TopoJSON сохраняет свойства объектов аналогично GeoJSON. После преобразования они доступны через стандартный API OpenLayers:
feature.get('name');
feature.get('population');
feature.getProperties();
Это позволяет использовать TopoJSON не только как геометрический формат, но и как контейнер для аналитических данных, связанных с географией.
В масштабных приложениях TopoJSON часто применяется для:
Основная роль формата заключается в снижении нагрузки на сеть и клиентский рендеринг при сохранении целостности топологических связей между объектами.