Обратное геокодирование (Reverse Geocoding) — процесс преобразования географических координат в человекочитаемый адрес или описание объекта местности. Если прямое геокодирование отвечает на вопрос «какие координаты соответствуют этому адресу?», то обратное геокодирование решает противоположную задачу: «какой адрес находится по этим координатам?».
В веб-картографии обратное геокодирование используется для:
В экосистеме Mapbox обратное геокодирование выполняется через Geocoding API, а Mapbox GL JS используется для получения координат пользователя или точки на карте и отображения результата.
Последовательность обработки данных обычно выглядит следующим образом:
Схема взаимодействия:
Клик по карте
↓
Получение longitude и latitude
↓
Запрос в Geocoding API
↓
JSON-ответ с адресом
↓
Отображение информации
Базовая настройка карты:
mapboxgl.accessToken = 'YOUR_MAPBOX_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [37.6176, 55.7558],
zoom: 10
});
HTML-контейнер:
<div id="map"></div>
CSS:
#map {
width: 100%;
height: 600px;
}
Для обратного геокодирования необходимо получить координаты выбранной точки.
Mapbox GL JS предоставляет объект события клика:
map.on('click', (event) => {
const lng = event.lngLat.lng;
const lat = event.lngLat.lat;
console.log(lng, lat);
});
Свойство lngLat содержит:
{
lng: 37.6176,
lat: 55.7558
}
Полученные координаты становятся входными данными для Geocoding API.
Формат URL обратного геокодирования:
https://api.mapbox.com/search/geocode/v6/reverse
Параметры:
| Параметр | Назначение |
|---|---|
| longitude | Долгота |
| latitude | Широта |
| access_token | Токен доступа |
| limit | Максимальное количество результатов |
| language | Язык ответа |
| types | Типы объектов |
Пример запроса:
async function reverseGeocode(lng, lat) {
const url =
`https://api.mapbox.com/search/geocode/v6/reverse?` +
`longitude=${lng}&latitude=${lat}` +
`&access_token=${mapboxgl.accessToken}`;
const response = await fetch(url);
const data = await response.json();
console.log(data);
}
Вызов:
map.on('click', (e) => {
reverseGeocode(
e.lngLat.lng,
e.lngLat.lat
);
});
Типичный ответ содержит массив объектов:
{
"features": [
{
"properties": {
"full_address": "Красная площадь, Москва"
},
"geometry": {
"coordinates": [
37.620393,
55.75396
]
}
}
]
}
Чаще всего используются:
data.features[0]
или
const place = data.features[0];
Основные данные:
place.properties.full_address
place.properties.name
place.properties.context
Наиболее востребованная информация — полный адрес.
async function reverseGeocode(lng, lat) {
const url =
`https://api.mapbox.com/search/geocode/v6/reverse?` +
`longitude=${lng}&latitude=${lat}` +
`&access_token=${mapboxgl.accessToken}`;
const response = await fetch(url);
const data = await response.json();
const address =
data.features[0].properties.full_address;
console.log(address);
}
Результат:
Красная площадь, Москва, Россия
Частый сценарий — показ адреса непосредственно на карте.
map.on('click', async (e) => {
const lng = e.lngLat.lng;
const lat = e.lngLat.lat;
const url =
`https://api.mapbox.com/search/geocode/v6/reverse?` +
`longitude=${lng}&latitude=${lat}` +
`&access_token=${mapboxgl.accessToken}`;
const response = await fetch(url);
const data = await response.json();
const address =
data.features[0].properties.full_address;
new mapboxgl.Popup()
.setLngLat([lng, lat])
.setHTML(`<strong>${address}</strong>`)
.addTo(map);
});
После клика пользователь увидит адрес выбранной точки.
Для визуального обозначения найденной точки удобно использовать маркер.
map.on('click', async (e) => {
const lng = e.lngLat.lng;
const lat = e.lngLat.lat;
new mapboxgl.Marker()
.setLngLat([lng, lat])
.addTo(map);
});
Комбинация маркера и всплывающего окна:
const marker = new mapboxgl.Marker()
.setLngLat([lng, lat]);
const popup = new mapboxgl.Popup()
.setHTML(address);
marker
.setPopup(popup)
.addTo(map);
Иногда требуется получить только один наиболее релевантный адрес.
Используется параметр:
limit=1
Пример:
const url =
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&limit=1` +
`&access_token=${mapboxgl.accessToken}`;
Это уменьшает объём ответа и ускоряет обработку.
API поддерживает множество языков.
Русский язык:
language=ru
Пример:
const url =
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&language=ru` +
`&access_token=${mapboxgl.accessToken}`;
Английский язык:
language=en`
Несколько языков:
language=ru,en
Обратное геокодирование может возвращать различные сущности:
Для фильтрации используется параметр:
types=
Пример только адресов:
types=address
Только населённые пункты:
types=place
Несколько типов:
types=address,street
Полный пример:
const url =
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&types=address` +
`&access_token=${mapboxgl.accessToken}`;
Координаты могут находиться далеко от конкретного адреса. В этом случае сервис возвращает ближайший известный объект.
Например:
{
"name": "Красная площадь"
}
или
{
"name": "Московский Кремль"
}
Такой подход особенно полезен для:
Обратное геокодирование может возвращать несколько вариантов.
Пример обхода результатов:
data.features.forEach(feature => {
console.log(
feature.properties.full_address
);
});
Формирование списка:
const addresses =
data.features.map(feature =>
feature.properties.full_address
);
console.log(addresses);
Mapbox GL JS поддерживает геолокацию браузера.
Добавление элемента управления:
const geolocate =
new mapboxgl.GeolocateControl({
trackUserLocation: true
});
map.addControl(geolocate);
Получение координат:
geolocate.on('geolocate', async (position) => {
const lng =
position.coords.longitude;
const lat =
position.coords.latitude;
reverseGeocode(lng, lat);
});
Функция обратного геокодирования:
async function reverseGeocode(lng, lat) {
const response = await fetch(
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&access_token=${mapboxgl.accessToken}`
);
const data = await response.json();
console.log(
data.features[0].properties.full_address
);
}
Не каждая точка имеет адрес.
Например:
Проверка:
if (!data.features.length) {
console.log(
'Адрес не найден'
);
return;
}
Без такой проверки возможна ошибка:
Cannot read properties of undefined
Работа с удалённым API всегда требует обработки исключений.
async function reverseGeocode(lng, lat) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Ошибка API');
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
}
Создание нового маркера после каждого клика может приводить к накоплению объектов.
Более эффективный вариант:
const marker =
new mapboxgl.Marker();
map.on('click', (e) => {
marker
.setLngLat(e.lngLat)
.addTo(map);
});
Теперь один и тот же маркер просто перемещается.
Распространённая структура:
async function reverseGeocode(lng, lat) {
const response =
await fetch(createUrl(lng, lat));
return response.json();
}
function createUrl(lng, lat) {
return (
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&access_token=${mapboxgl.accessToken}`
);
}
function showAddress(address) {
document
.querySelector('#address')
.textContent = address;
}
Использование:
map.on('click', async (e) => {
const data =
await reverseGeocode(
e.lngLat.lng,
e.lngLat.lat
);
const address =
data.features[0]
.properties.full_address;
showAddress(address);
});
Полноценная реализация обратного геокодирования по клику:
mapboxgl.accessToken = 'YOUR_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [37.6176, 55.7558],
zoom: 11
});
const marker = new mapboxgl.Marker();
map.on('click', async (e) => {
const lng = e.lngLat.lng;
const lat = e.lngLat.lat;
const response = await fetch(
`https://api.mapbox.com/search/geocode/v6/reverse` +
`?longitude=${lng}` +
`&latitude=${lat}` +
`&limit=1` +
`&language=ru` +
`&access_token=${mapboxgl.accessToken}`
);
const data = await response.json();
if (!data.features.length) {
return;
}
const address =
data.features[0]
.properties.full_address;
marker
.setLngLat([lng, lat])
.addTo(map);
new mapboxgl.Popup()
.setLngLat([lng, lat])
.setHTML(address)
.addTo(map);
});
Такая схема охватывает основные сценарии работы с обратным геокодированием в Mapbox GL JS: получение координат, обращение к Geocoding API, извлечение адресных данных, локализацию результатов, фильтрацию типов объектов, обработку ошибок и отображение найденной информации непосредственно на карте.