Геолокация и карты в JavaScript (Node.js): библиотеки и примеры

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Геолокация и карты в JavaScript (Node.js)

Работа с географическими данными и отображением карт — одна из ключевых задач современных веб-приложений. В экосистеме Node.js существует множество библиотек, позволяющих обрабатывать координаты, строить маршруты, выполнять обратное геокодирование и рендерить интерактивные карты. В этой статье мы рассмотрим основные инструменты и приведём практические примеры кода для серверной части (Node.js).

1. Основные библиотеки для работы с геоданными

1.1. Leaflet (клиентская часть) и node-leaflet

Leaflet — самая популярная JavaScript-библиотека для интерактивных карт. Она работает на стороне браузера, но для Node.js существует пакет leaflet (через npm install leaflet), который позволяет рендерить карты на сервере с помощью leaflet-headless или использовать данные в формате GeoJSON.

Пример генерации карты в виде изображения на сервере (с помощью leaflet-static):

const L = require('leaflet');
const { createCanvas } = require('canvas');

const map = L.map(createCanvas(800, 600), {
    center: [55.751244, 37.618423], // Москва
    zoom: 10
});

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors'
}).addTo(map);

// Экспорт в PNG (упрощённо)
const buffer = map.getCanvas().toBuffer();
require('fs').writeFileSync('map.png', buffer);

1.2. OpenStreetMap (OSM) и Overpass API

OpenStreetMap предоставляет бесплатные тайлы и API для поиска объектов. В Node.js для работы с OSM часто используют пакет osmosis или прямые HTTP-запросы к https://nominatim.openstreetmap.org.

Пример обратного геокодирования (получение адреса по координатам):

const fetch = require('node-fetch');

async function reverseGeocode(lat, lon) {
    const url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lon}`;
    const response = await fetch(url, {
        headers: { 'User-Agent': 'PythonLibExample/1.0' }
    });
    const data = await response.json();
    return data.display_name;
}

reverseGeocode(55.751244, 37.618423).then(addr => console.log(addr));
// Результат: "Москва, Россия, Красная площадь"

1.3. Turf.js — геопространственный анализ

Turf.js — мощная библиотека для выполнения геометрических операций: буферизация, объединение полигонов, расчёт расстояний, площади и т.д. Работает как в браузере, так и в Node.js.

Пример вычисления расстояния между двумя точками (в километрах):

const turf = require('@turf/turf');

const point1 = turf.point([37.618423, 55.751244]); // [lon, lat]
const point2 = turf.point([30.315868, 59.939095]); // Санкт-Петербург

const distance = turf.distance(point1, point2, { units: 'kilometers' });
console.log(`Расстояние: ${distance.toFixed(2)} км`); // ≈ 634.5 км

1.4. GeoJSON и shapefile

GeoJSON — формат для хранения географических структур (точки, линии, полигоны). В Node.js для работы с ним достаточно встроенного JSON.parse, а для чтения shape-файлов используют пакет shapefile.

const shapefile = require('shapefile');

shapefile.open('path/to/file.shp')
    .then(source => source.read()
        .then(function log(result) {
            if (result.done) return;
            console.log(result.value); // GeoJSON Feature
            return source.read().then(log);
        }))
    .catch(error => console.error(error));

2. Продвинутые инструменты

2.1. Mapbox GL JS (Node.js)

Mapbox предоставляет коммерческую платформу с высокодетализированными картами. Для серверного рендеринга используйте @mapbox/mapbox-gl-native. Требуется ключ API.

2.2. Nominatim (геокодинг)

Помимо обратного геокодирования, Nominatim позволяет искать объекты по названию. Пример:

async function searchPlace(query) {
    const url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}`;
    const res = await fetch(url, { headers: { 'User-Agent': 'PythonLib' } });
    const data = await res.json();
    return data.map(item => ({ name: item.display_name, lat: item.lat, lon: item.lon }));
}

searchPlace('Эйфелева башня').then(console.log);

3. Комплексный

Рекомендаций