Координаты событий

В экосистеме Mapbox GL JS координаты являются фундаментом всей модели взаимодействия пользователя с картой. Любое событие — клик, движение мыши, касание экрана — одновременно существует в двух пространствах: экранных пикселях и географических координатах. Понимание того, как происходит переход между этими системами, определяет качество всей логики обработки событий.

Каждое событие на карте содержит как минимум две системы координат:

  • Pixel coordinates (screen space) — координаты относительно контейнера карты в пикселях
  • LngLat (geographic space) — долгота и широта в мировых координатах

При обработке событий это различие критично:

map.on('click', (e) => {
  console.log(e.point);   // { x: Number, y: Number } — пиксели
  console.log(e.lngLat);  // { lng: Number, lat: Number } — география
});

e.point всегда привязан к текущему состоянию DOM-контейнера карты, тогда как e.lngLat учитывает все трансформации: масштабирование, вращение, наклон и проекцию.

Географические координаты события

Объект LngLat представляет собой стандартную пару значений:

  • lng — долгота (от -180 до 180)
  • lat — широта (от -85.0511 до 85.0511 в Web Mercator)

Mapbox GL JS автоматически нормализует координаты при пересечении границ карты. Например, при панорамировании через 180-й меридиан значение longitude может «перепрыгивать», но визуально точка останется стабильной.

map.on('mousemove', (e) => {
  const { lng, lat } = e.lngLat;
  console.log(`Longitude: ${lng}, Latitude: ${lat}`);
});

Экранные координаты и система пикселей

Система e.point используется для операций, связанных с рендерингом и взаимодействием с слоями:

  • выбор объектов на карте
  • определение попадания курсора
  • построение интерфейсных элементов относительно карты
map.on('click', (e) => {
  const pixel = e.point;
  console.log(pixel.x, pixel.y);
});

Эти координаты всегда считаются относительно контейнера <div> карты и зависят от CSS-трансформаций.

Преобразование координат: project и unproject

Mapbox GL JS предоставляет прямые методы конвертации между системами координат:

project (география → пиксели)

const lngLat = { lng: 37.6173, lat: 55.7558 };
const point = map.project(lngLat);

console.log(point); // { x, y }

Метод учитывает текущие:

  • zoom
  • pitch
  • bearing
  • center карты

unproject (пиксели → география)

const point = { x: 200, y: 300 };
const lngLat = map.unproject(point);

console.log(lngLat); // { lng, lat }

Это основной инструмент для построения пользовательских взаимодействий вне стандартных событий.

События мыши и их координатная модель

Все pointer-события в Mapbox GL JS содержат одинаковую структуру координат:

  • mousedown
  • mouseup
  • click
  • dblclick
  • mousemove
  • mouseenter
  • mouseleave

Пример унифицированной обработки:

map.on('mousemove', (e) => {
  updateUI({
    pixel: e.point,
    geo: e.lngLat
  });
});

Важно учитывать, что mousemove генерируется с высокой частотой, поэтому работа с координатами должна быть оптимизирована.

Определение объектов по координатам события

Одной из ключевых операций является сопоставление координаты с объектами слоя:

map.on('click', (e) => {
  const features = map.queryRenderedFeatures(e.point, {
    layers: ['cities-layer']
  });

  console.log(features);
});

Метод queryRenderedFeatures использует именно e.point, а не lngLat, так как поиск выполняется в экранном пространстве рендеринга WebGL.

Координаты при работе с курсором и drag-событиями

Перетаскивание карты создаёт непрерывный поток координат:

map.on('drag', (e) => {
  console.log(e.point);
  console.log(e.lngLat);
});

При этом:

  • point изменяется относительно DOM-движения
  • lngLat отражает реальное смещение камеры в географическом пространстве

Координаты и трансформация карты

Сложность работы с событиями возрастает при включении:

  • bearing (поворот карты)
  • pitch (наклон камеры)

В этих режимах e.point больше не соответствует простой декартовой проекции экрана. Mapbox GL JS применяет матрицы трансформации WebGL, и преобразование происходит через внутреннюю камеру.

Пример:

map.setBearing(45);
map.setPitch(60);

map.on('click', (e) => {
  console.log(e.lngLat);
});

Даже при сильном наклоне географические координаты остаются стабильными, тогда как пиксельные координаты становятся искажёнными перспективой.

Использование событий для построения интерактивных слоёв

Координаты событий часто используются для динамического создания объектов:

map.on('click', (e) => {
  map.addSource('point', {
    type: 'geojson',
    data: {
      type: 'Feature',
      geometry: {
        type: 'Point',
        coordinates: [e.lngLat.lng, e.lngLat.lat]
      }
    }
  });
});

Здесь происходит прямое преобразование события в GeoJSON-структуру, где координаты строго соответствуют стандарту [longitude, latitude].

Границы карты и нормализация координат

Mapbox GL JS использует Web Mercator проекцию, поэтому:

  • широта ограничена диапазоном ±85.0511°
  • долгота циклична

При работе с событиями важно учитывать нормализацию:

map.on('click', (e) => {
  const normalized = e.lngLat.wrap();
  console.log(normalized);
});

Метод wrap() полезен при работе с повторяющимися мирами (world copies).

Координаты в touch-событиях

На мобильных устройствах структура координат сохраняется идентичной:

map.on('touchstart', (e) => {
  console.log(e.point);
  console.log(e.lngLat);
});

Разница заключается лишь в источнике pointer-события, но модель координат остаётся унифицированной.

Связь координат событий с камерой

Каждое событие можно рассматривать как проекцию положения камеры:

  • lngLat — направление центра луча камеры в мире
  • point — пересечение этого луча с плоскостью экрана

При изменении камеры изменяется вся система преобразования, но API событий остаётся стабильным интерфейсом.

Использование координат для построения пользовательских инструментов

На основе событий строятся ключевые инструменты:

  • рисование линий
  • измерение расстояний
  • выделение областей
  • построение маршрутов

Пример накопления координат:

const path = [];

map.on('click', (e) => {
  path.push([e.lngLat.lng, e.lngLat.lat]);
});

Эта модель лежит в основе большинства интерактивных GIS-функций.