GeoJSON является одним из ключевых форматов обмена геопространственными данными в веб-картографии. В контексте MapLibre GL JS он используется как источник векторных данных, который может быть отрисован на карте в виде точек, линий и полигонов.
В отличие от тайловых источников (vector tiles, raster tiles), GeoJSON-источник представляет собой целостный набор геометрий, загружаемый в память клиента и обрабатываемый непосредственно в браузере. Это делает его особенно удобным для:
Наиболее распространённый сценарий — размещение .geojson
файла на сервере и загрузка через URL.
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://demotiles.maplibre.org/style.json",
center: [37.6173, 55.7558],
zoom: 10
});
map.on("load", () => {
map.addSource("cities", {
type: "geojson",
data: "https://example.com/data/cities.geojson"
});
map.addLayer({
id: "cities-points",
type: "circle",
source: "cities",
paint: {
"circle-radius": 6,
"circle-color": "#ff5500"
}
});
});
В данном случае MapLibre самостоятельно выполняет HTTP-запрос, загружает файл и парсит GeoJSON.
Ключевой момент: URL может быть как абсолютным, так и относительным, если сервер корректно настроен.
При необходимости явного контроля над загрузкой используется
fetch, после чего данные передаются в MapLibre как
объект.
map.on("load", async () => {
const response = await fetch("/data/cities.geojson");
const geojson = await response.json();
map.addSource("cities", {
type: "geojson",
data: geojson
});
map.addLayer({
id: "cities-fill",
type: "circle",
source: "cities",
paint: {
"circle-radius": 5,
"circle-color": "#3b82f6"
}
});
});
Такой подход позволяет:
При работе с пользовательскими файлами используется механизм
FileReader.
const input = document.getElementById("fileInput");
input.addEventListener("change", (event) => {
const file = event.target.files[0];
const reader = new FileReader();
reader.onl oad = (e) => {
const geojson = JSON.parse(e.target.result);
map.addSource("uploaded-data", {
type: "geojson",
data: geojson
});
map.addLayer({
id: "uploaded-layer",
type: "fill",
source: "uploaded-data",
paint: {
"fill-color": "#10b981",
"fill-opacity": 0.5
}
});
};
reader.readAsText(file);
});
Этот способ используется в интерфейсах загрузки данных пользователем, где GeoJSON не хранится заранее на сервере.
MapLibre GL JS поддерживает стандарт RFC 7946. Базовая структура выглядит следующим образом:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [37.6173, 55.7558]
},
"properties": {
"name": "Москва"
}
}
]
}
MapLibre GL JS позволяет динамически изменять данные источника.
map.getSource("cities").setData(newGeojson);
Это основной механизм обновления данных без пересоздания слоя.
GeoJSON не поддерживает частичное обновление структуры напрямую, поэтому применяется один из подходов:
setDataconst source = map.getSource("cities");
fetch("/data/updated.geojson")
.then(res => res.json())
.then(data => {
source.setData(data);
});
При работе с GeoJSON важно учитывать объём данных, поскольку весь файл загружается в память браузера.
const filtered = geojson.features.filter(f => f.properties.active);
Перед загрузкой применяется алгоритм упрощения (например, Douglas-Peucker), чтобы уменьшить количество координат.
map.addSource("cities-small", {...});
map.addSource("cities-large", {...});
После загрузки данные можно динамически фильтровать на уровне слоя:
map.addLayer({
id: "cities-filtered",
type: "circle",
source: "cities",
filter: ["==", ["get", "type"], "capital"],
paint: {
"circle-color": "#e11d48",
"circle-radius": 7
}
});
Фильтры MapLibre работают на стороне рендера и не требуют изменения GeoJSON.
При необходимости объединения нескольких файлов используется агрегация:
Promise.all([
fetch("/data/cities.geojson").then(r => r.json()),
fetch("/data/roads.geojson").then(r => r.json())
]).then(([cities, roads]) => {
map.addSource("cities", { type: "geojson", data: cities });
map.addSource("roads", { type: "geojson", data: roads });
});
Каждый источник отображается отдельным слоем, что позволяет разделять стили и поведение.
При загрузке через HTTP полезно учитывать кэширование браузера.
Cache-ControlETagLast-ModifiedЭто снижает нагрузку при повторных открытиях карты.
GeoJSON может быть повреждён или недоступен, поэтому требуется обработка ошибок:
fetch("/data/cities.geojson")
.then(res => {
if (!res.ok) throw new Error("Ошибка загрузки");
return res.json();
})
.then(data => {
map.getSource("cities").setData(data);
})
.catch(err => {
console.error("GeoJSON не загружен", err);
});
GeoJSON часто формируется программно:
const points = [];
for (let i = 0; i < 100; i++) {
points.push({
type: "Feature",
geometry: {
type: "Point",
coordinates: [
37 + Math.random(),
55 + Math.random()
]
},
properties: {
id: i
}
});
}
map.addSource("random", {
type: "geojson",
data: {
type: "FeatureCollection",
features: points
}
});
Такой подход используется в аналитических и симуляционных задачах.
После загрузки GeoJSON он становится основой для различных типов слоёв:
circle — точкиline — линии маршрутовfill — полигоныsymbol — подписи и иконкиОдин источник может использоваться несколькими слоями одновременно:
map.addLayer({
id: "cities-labels",
type: "symbol",
source: "cities",
layout: {
"text-field": ["get", "name"]
}
});