Получение координат по клику

В основе взаимодействия с картой лежит система событий, предоставляемая экземпляром карты. Основное событие для получения координат — click, срабатывающее при завершении пользовательского нажатия на карту. В OpenLayers событие передаёт объект, содержащий координаты, пиксель и контекст слоя.

map.on('click', function (event) {
    console.log(event);
});

Объект event содержит ключевые поля:

  • coordinate — координаты точки в системе проекции карты
  • pixel — координаты пикселя внутри контейнера карты
  • dragging — индикатор перетаскивания (в некоторых версиях)

Наиболее часто используется именно event.coordinate, поскольку он уже преобразован в систему координат карты (обычно EPSG:3857).


Координаты в проекции карты

OpenLayers по умолчанию работает в проекции Web Mercator (EPSG:3857). Координаты, получаемые через event.coordinate, представлены в метрах относительно проекции.

map.on('click', function (event) {
    const coordinate = event.coordinate;
    console.log('Координаты в проекции карты:', coordinate);
});

Пример значения:

[4185821.12, 7512345.67]

Такие координаты неудобны для отображения пользователю, поэтому часто требуется преобразование в географические координаты (долгота/широта).


Преобразование в WGS84 (долгота и широта)

Для перевода координат используется модуль ol/proj, содержащий функцию toLonLat.

import { toLonLat } from 'ol/proj';

map.on('click', function (event) {
    const lonLat = toLonLat(event.coordinate);
    console.log('Долгота и широта:', lonLat);
});

Результат:

[longitude, latitude]

Пример:

[73.3498, 49.8064]

При необходимости обратного преобразования используется fromLonLat:

import { fromLonLat } from 'ol/proj';

const coord = fromLonLat([73.3498, 49.8064]);

Получение координат через пиксели

Событие клика содержит также пиксельную позицию относительно контейнера карты. Это значение используется для взаимодействия с экранными координатами и слоями.

map.on('click', function (event) {
    const pixel = event.pixel;
    console.log('Пиксель:', pixel);
});

Для получения координат по пикселю используется метод карты:

map.on('click', function (event) {
    const coordinate = map.getCoordinateFromPixel(event.pixel);
    console.log(coordinate);
});

Оба подхода (event.coordinate и getCoordinateFromPixel) обычно дают одинаковый результат, однако event.coordinate является более прямым и предпочтительным.


Различие между координатами пикселя и карты

Пиксельная система координат привязана к DOM-элементу карты:

  • начало координат — левый верхний угол контейнера
  • ось X направлена вправо
  • ось Y направлена вниз

Координаты карты:

  • зависят от проекции
  • могут быть в метрах (EPSG:3857)
  • или в градусах (EPSG:4326 после преобразования)

Фильтрация кликов по объектам карты

Событие клика может использоваться для определения объектов, находящихся в точке клика. Метод forEachFeatureAtPixel позволяет получить все объекты слоя под курсором.

map.on('click', function (event) {
    map.forEachFeatureAtPixel(event.pixel, function (feature, layer) {
        console.log('Найден объект:', feature);
    });
});

Это позволяет связывать координаты клика с конкретными географическими объектами.


Получение координат с учётом нескольких слоёв

При наличии нескольких слоёв порядок перебора определяется порядком их отображения. Дополнительно можно фильтровать слои:

map.on('click', function (event) {
    map.forEachFeatureAtPixel(event.pixel, function (feature, layer) {
        if (layer && layer.get('type') === 'vector') {
            console.log(feature);
        }
    });
});

Использование точности координат

Координаты в OpenLayers представляют собой числа с плавающей точкой. При работе с отображением или хранением часто применяется округление.

map.on('click', function (event) {
    const coord = event.coordinate;

    const rounded = [
        Math.round(coord[0] * 100) / 100,
        Math.round(coord[1] * 100) / 100
    ];

    console.log(rounded);
});

При преобразовании в географические координаты также часто применяется ограничение количества знаков:

import { toLonLat } from 'ol/proj';

map.on('click', function (event) {
    const [lon, lat] = toLonLat(event.coordinate);

    console.log([
        lon.toFixed(6),
        lat.toFixed(6)
    ]);
});

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

Помимо клика, координаты могут извлекаться при движении указателя:

map.on('pointermove', function (event) {
    const coordinate = event.coordinate;
    console.log(coordinate);
});

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


Координаты в различных проекциях

OpenLayers поддерживает работу с различными системами координат через библиотеку proj4.

Типичный сценарий:

  • карта в EPSG:3857
  • данные пользователя в EPSG:4326
  • отображение требует преобразования между ними
import { transform } from 'ol/proj';

map.on('click', function (event) {
    const transformed = transform(
        event.coordinate,
        'EPSG:3857',
        'EPSG:4326'
    );

    console.log(transformed);
});

Центрирование карты по координатам клика

Координаты клика часто используются для изменения центра карты:

map.on('click', function (event) {
    const view = map.getView();

    view.setCenter(event.coordinate);
});

При необходимости добавляется анимация:

view.animate({
    center: event.coordinate,
    duration: 500
});

Использование координат для добавления объектов

Клик может использоваться для динамического создания геометрии:

import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';

const source = new VectorSource();
const layer = new VectorLayer({
    source: source
});

map.addLayer(layer);

map.on('click', function (event) {
    const feature = new Feature({
        geometry: new Point(event.coordinate)
    });

    source.addFeature(feature);
});

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

Сбор последовательности координат используется для построения линий и полигонов.

const coords = [];

map.on('click', function (event) {
    coords.push(event.coordinate);
    console.log(coords);
});

Дальнейшая обработка может включать создание геометрий:

import LineString from 'ol/geom/LineString';

const line = new LineString(coords);

Ограничение области получения координат

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

map.on('click', function (event) {
    let found = false;

    map.forEachFeatureAtPixel(event.pixel, function (feature, layer) {
        if (layer && layer.get('selectable')) {
            found = true;
        }
    });

    if (!found) return;

    console.log(event.coordinate);
});

Работа с точностью при разных масштабах

При увеличении масштаба координаты становятся более чувствительными. Векторная точность зависит от:

  • уровня зума
  • источника данных
  • системы проекции

Для стабилизации поведения часто применяется привязка к сетке:

function snap(value, precision) {
    return Math.round(value / precision) * precision;
}

map.on('click', function (event) {
    const [x, y] = event.coordinate;

    const snapped = [
        snap(x, 10),
        snap(y, 10)
    ];

    console.log(snapped);
});

Синхронизация координат с внешними интерфейсами

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

map.on('click', function (event) {
    const [lon, lat] = toLonLat(event.coordinate);

    document.getElementById('lon').value = lon;
    document.getElementById('lat').value = lat;
});

Контроль систем координат слоя и карты

При работе с несколькими слоями важно учитывать, что каждый слой может использовать собственную проекцию. OpenLayers выполняет преобразование автоматически при корректной настройке projection в View.

import View from 'ol/View';

const view = new View({
    projection: 'EPSG:3857'
});

Несоответствие проекций приводит к смещению координат при клике.


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

Координаты клика могут использоваться для:

  • расчёта расстояний между точками
  • построения маршрутов
  • анализа плотности объектов
  • геофенсинга

Простейший пример вычисления расстояния между двумя кликами:

import { getDistance } from 'ol/sphere';

let first = null;

map.on('click', function (event) {
    if (!first) {
        first = event.coordinate;
        return;
    }

    const distance = getDistance(
        toLonLat(first),
        toLonLat(event.coordinate)
    );

    console.log(distance);

    first = null;
});