При работе с картами практически любая операция связана с координатами и экранными позициями. Для этих целей в Mapbox GL JS используются два фундаментальных класса:
Эти классы используются практически во всех подсистемах библиотеки: при позиционировании маркеров, обработке событий мыши, анимации камеры, преобразовании координат и вычислении расстояний.
Объект LngLat хранит географические координаты в
формате:
new mapboxgl.LngLat(longitude, latitude);
Где:
longitude — долгота;latitude — широта.Пример:
const location = new mapboxgl.LngLat(37.6176, 55.7558);
console.log(location.lng);
console.log(location.lat);
Результат:
37.6176
55.7558
В Mapbox GL JS всегда используется порядок:
[longitude, latitude]
а не:
[latitude, longitude]
Правильно:
[37.6176, 55.7558]
Неправильно:
[55.7558, 37.6176]
Это одна из наиболее распространённых ошибок при работе с картографическими библиотеками.
const point = new mapboxgl.LngLat(
37.6176,
55.7558
);
Во многих API допускается использование массива:
const center = [37.6176, 55.7558];
map.setCenter(center);
Внутри библиотеки такой массив автоматически преобразуется в объект
LngLat.
Содержит долготу.
const position = new mapboxgl.LngLat(37.6176, 55.7558);
console.log(position.lng);
Результат:
37.6176
Содержит широту.
console.log(position.lat);
Результат:
55.7558
Преобразует объект в массив координат.
const point = new mapboxgl.LngLat(
37.6176,
55.7558
);
const array = point.toArray();
console.log(array);
Результат:
[37.6176, 55.7558]
Метод полезен при взаимодействии с GeoJSON и внешними API.
Возвращает строковое представление координат.
const point = new mapboxgl.LngLat(
37.6176,
55.7558
);
console.log(point.toString());
Пример результата:
LngLat(37.6176, 55.7558)
Такое представление удобно использовать для отладки.
Долгота может выходить за диапазон:
-180 ... 180
Например:
const point = new mapboxgl.LngLat(
220,
55
);
Координата 220° эквивалентна координате
-140°.
Метод wrap() автоматически приводит долготу к
допустимому диапазону.
const wrapped = point.wrap();
console.log(wrapped.lng);
Результат:
-140
Пример использования:
const current = map.getCenter().wrap();
Это особенно полезно на картах с бесконечной прокруткой по горизонтали.
Позволяет вычислить расстояние между двумя географическими точками.
const moscow = new mapboxgl.LngLat(
37.6176,
55.7558
);
const spb = new mapboxgl.LngLat(
30.3351,
59.9343
);
const distance = moscow.distanceTo(spb);
console.log(distance);
Результат возвращается в метрах.
Пример вывода:
633021.5
То есть примерно:
633 км
Координаты центра карты задаются через объект LngLat
либо массив.
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [37.6176, 55.7558],
zoom: 10
});
Внутри библиотеки значение будет преобразовано в
LngLat.
const center = map.getCenter();
console.log(center);
Результат:
LngLat
Получение отдельных координат:
console.log(center.lng);
console.log(center.lat);
map.flyTo({
center: new mapboxgl.LngLat(
30.3351,
59.9343
),
zoom: 12
});
Либо сокращённая запись:
map.flyTo({
center: [30.3351, 59.9343]
});
map.panTo(
new mapboxgl.LngLat(
37.6176,
55.7558
)
);
Каждый маркер хранит географическое положение как объект
LngLat.
Создание маркера:
new mapboxgl.Marker()
.setLngLat([37.6176, 55.7558])
.addTo(map);
Получение координат:
const marker = new mapboxgl.Marker()
.setLngLat([37.6176, 55.7558]);
const position = marker.getLngLat();
console.log(position.lng);
console.log(position.lat);
При клике карта возвращает координаты точки на поверхности Земли.
map.on('click', (event) => {
console.log(event.lngLat);
});
Объект:
LngLat
Получение координат:
map.on('click', (event) => {
console.log(event.lngLat.lng);
console.log(event.lngLat.lat);
});
Если LngLat описывает положение на Земле, то
Point описывает положение внутри контейнера карты.
Координаты измеряются в пикселях.
Создание объекта:
const point = new mapboxgl.Point(
300,
150
);
Здесь:
x = 300 px
y = 150 px
Начало координат находится в левом верхнем углу контейнера карты.
(0,0)
┌─────────────────────► X
│
│
│
▼
Y
Поэтому:
new mapboxgl.Point(0, 0);
соответствует левому верхнему углу карты.
Горизонтальная координата.
const point = new mapboxgl.Point(250, 100);
console.log(point.x);
Результат:
250
Вертикальная координата.
console.log(point.y);
Результат:
100
При клике по карте объект события содержит экранную позицию курсора.
map.on('click', (event) => {
console.log(event.point);
});
Результат:
Point
Получение координат:
map.on('click', (event) => {
console.log(event.point.x);
console.log(event.point.y);
});
При клике карта возвращает оба объекта.
map.on('click', (event) => {
console.log(event.point);
console.log(event.lngLat);
});
Например:
Point(450, 320)
и
LngLat(37.6176, 55.7558)
Первый объект показывает положение курсора внутри HTML-контейнера.
Второй показывает реальное положение точки на поверхности Земли.
Метод unproject() преобразует экранные координаты в
географические.
const point = new mapboxgl.Point(
300,
200
);
const lngLat = map.unproject(point);
console.log(lngLat);
Результат:
LngLat
Схема преобразования:
Point → LngLat
Обратная операция выполняется методом project().
const point = map.project(
[37.6176, 55.7558]
);
console.log(point);
Результат:
Point
Схема:
LngLat → Point
map.on('click', (event) => {
const screenPoint = event.point;
const geoPoint = map.unproject(screenPoint);
console.log(screenPoint);
console.log(geoPoint);
});
Возможный результат:
Point(412, 289)
LngLat(37.6176, 55.7558)
Объекты Point поддерживают ряд математических
операций.
Сложение координат.
const a = new mapboxgl.Point(10, 20);
const b = new mapboxgl.Point(5, 3);
const result = a.add(b);
console.log(result);
Результат:
Point(15, 23)
Вычитание координат.
const result = a.sub(b);
Результат:
Point(5, 17)
Умножение координат.
const result = a.mult(2);
Результат:
Point(20, 40)
Деление координат.
const result = a.div(2);
Результат:
Point(5, 10)
Частая задача — вычислить экранную позицию географической точки.
const lngLat = [37.6176, 55.7558];
const point = map.project(lngLat);
console.log(point.x);
console.log(point.y);
Такой подход используется при:
Метод поиска объектов может принимать экранную точку.
Поиск объектов под курсором:
map.on('click', (event) => {
const features =
map.queryRenderedFeatures(
event.point
);
console.log(features);
});
Поиск внутри области:
const bbox = [
new mapboxgl.Point(100, 100),
new mapboxgl.Point(300, 300)
];
const features =
map.queryRenderedFeatures(bbox);
Здесь поиск выполняется по прямоугольной области экрана.
Оба класса описывают одну и ту же точку в разных системах координат.
Схематично процесс выглядит следующим образом:
Географические координаты
↓
LngLat
↓ project()
↓
Point
↓
Экран контейнера
Обратное преобразование:
Экран контейнера
↓
Point
↓ unproject()
↓
LngLat
↓
Географические координаты
Именно через постоянные преобразования между LngLat и
Point Mapbox GL JS связывает географическое пространство
карты с пикселями браузерного окна, обеспечивая работу маркеров,
всплывающих окон, пользовательских интерфейсов, анимаций и интерактивных
событий.