Географические линии на карте в D3 строятся поверх проекций и
представляют собой результат преобразования геодезических координат в
экранные. Визуализация маршрутов, параллелей и меридианов опирается на
географический стек D3.js, где ключевую роль играет генерация геометрии
и её последующее отображение через d3.geoPath().
Географическая сетка (graticule) — это регулярная система линий широты и долготы, формирующая каркас карты. Она не несёт смысловой нагрузки данных, но задаёт визуальную ориентацию, позволяя сопоставлять объекты в пространстве.
В D3 сетка создаётся с помощью d3.geoGraticule(),
который генерирует GeoJSON-геометрию типа MultiLineString. Эти линии
затем проходят через географическую проекцию и отрисовываются как
SVG-пути.
Базовая структура:
const graticule = d3.geoGraticule();
По умолчанию создаётся сетка с шагом 10° по широте и долготе, охватывающая весь глобус.
Функция d3.geoGraticule() возвращает генератор, который
можно настраивать:
Основные параметры:
const graticule = d3.geoGraticule()
.step([10, 10])
.extent([[-180, -90], [180, 90]]);
Определяет интервал между линиями:
x — шаг долгот (меридианы)y — шаг широт (параллели)Например, шаг 5° создаёт плотную сетку, подходящую для детализированных карт:
d3.geoGraticule().step([5, 5]);
Ограничивает область генерации линий. Это особенно важно для региональных карт.
d3.geoGraticule()
.extent([[20, 30], [50, 60]]);
В этом случае сетка строится только внутри заданного прямоугольника в географических координатах.
Дополнительные параметры позволяют выделять более толстые линии:
stepMajor — шаг основных линийextentMajor — область основных линийd3.geoGraticule()
.stepMinor([2, 2])
.stepMajor([10, 10]);
Это используется для визуального разделения структуры сетки: тонкие линии для деталей, толстые — для ключевых делений.
Генерация геометрии — только первый этап. Для отображения используется географический путь:
const projection = d3.geoMercator()
.scale(150)
.translate([width / 2, height / 2]);
const path = d3.geoPath().projection(projection);
После этого сетка добавляется в SVG:
svg.append("path")
.datum(graticule())
.attr("d", path)
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr("stroke-width", 0.5);
Метод .datum(graticule()) передаёт GeoJSON-объект,
содержащий линии сетки.
Сетка координат — статическая структура. Маршруты и линии движения — динамические геометрические объекты.
Маршруты обычно задаются через GeoJSON LineString:
const route = {
type: "LineString",
coordinates: [
[37.6173, 55.7558],
[30.3351, 59.9343]
]
};
Отрисовка:
svg.append("path")
.datum(route)
.attr("d", path)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 2);
Здесь ключевое отличие: линии маршрутов зависят от данных, а graticule — от математической структуры координатной системы.
При соединении точек на сфере прямая линия на экране не всегда соответствует кратчайшему пути на поверхности Земли. D3 учитывает это через географические проекции.
Для более точных маршрутов используется интерполяция:
const interpolate = d3.geoInterpolate(
[37.6173, 55.7558],
[139.6917, 35.6895]
);
Это позволяет строить промежуточные точки вдоль великого круга.
Типичная карта содержит оба слоя:
Порядок отрисовки критичен:
svg.append("path")
.datum(graticule())
.attr("d", path)
.attr("fill", "none")
.attr("stroke", "#e0e0e0");
svg.append("path")
.datum(worldGeoJSON)
.attr("d", path)
.attr("fill", "#f5f5f5")
.attr("stroke", "#999");
svg.append("path")
.datum(route)
.attr("d", path)
.attr("stroke", "steelblue");
Сетка всегда рисуется первой, иначе она перекроет данные.
d3.geoGraticule() поддерживает генерацию внешнего
контура:
const graticule = d3.geoGraticule()
.step([10, 10])
.outline(true);
Контур создаёт замкнутую линию вокруг области сетки, что полезно для визуального ограничения карты.
Выбор шага напрямую влияет на восприятие карты:
Плотность часто адаптируется под масштаб проекции:
function getStep(scale) {
if (scale > 200) return [2, 2];
if (scale > 100) return [5, 5];
return [10, 10];
}
При интерактивном зуме сетка может пересчитываться:
function update() {
svg.selectAll("path.graticule")
.datum(graticule())
.attr("d", path);
}
Это позволяет сохранять корректную визуальную плотность при изменении масштаба проекции.
d3.geoGraticule() независим от проекции, но визуальный
результат зависит от неё:
d3.geoMercator() — искажение к полюсамd3.geoOrthographic() — глобус без искаженийd3.geoNaturalEarth1() — компромиссная проекцияНа ортографической проекции сетка приобретает дугообразный вид:
const projection = d3.geoOrthographic()
.scale(250)
.translate([width / 2, height / 2]);
Визуальная иерархия строится через CSS или SVG-атрибуты:
.attr("stroke", "#bbb")
.attr("stroke-opacity", 0.6)
.attr("stroke-width", 0.7)
Для выделения основных линий можно использовать два слоя:
const graticuleMinor = d3.geoGraticule().step([2, 2]);
const graticuleMajor = d3.geoGraticule().step([10, 10]);
Маршруты часто используются для визуализации потоков:
В таких случаях толщина линии может кодировать интенсивность:
.attr("stroke-width", d => scale(d.value))
Для создания эффекта перемещения используется интерполяция координат:
const t = 0.3;
const point = interpolate(t);
Далее точка может быть отображена как маркер, движущийся по линии маршрута.
Сетка выполняет роль координатного каркаса, маршруты — смыслового слоя. Их совместное использование позволяет:
При высокой плотности данных сетка становится вспомогательным инструментом ориентации, а маршруты — основным носителем информации.
Внутренне d3.geoGraticule() строит линии как набор
сегментов по меридианам и параллелям. Каждая линия — это цепочка
координат, которая затем проходит через проекцию.
Это означает, что:
Такая модель обеспечивает гибкость при интерактивной работе с картой.
Типичная архитектура SVG-карты:
Каждый слой изолирован и управляется отдельно через
d3.selection().
При пересечении маршрутов и сетки важна визуальная иерархия:
Так достигается читаемость даже при плотной визуализации.