В OpenLayers вращение карты реализуется на уровне представления
(View) и дополняется набором интеракций и UI-контролов.
Базовая сущность — свойство rotation, задающее угол
поворота карты в радианах. Вся система взаимодействий строится вокруг
преобразования координат и матрицы отображения слоя.
ViewКлючевым элементом является объект представления карты:
import View from 'ol/View';
const view = new View({
center: [0, 0],
zoom: 2,
rotation: 0
});
Параметр rotation задаётся в радианах и определяет угол
поворота против часовой стрелки. Изменение значения приводит к
перерасчёту матрицы трансформации отображения всех слоёв.
Изменение вращения динамически:
view.setRotation(Math.PI / 4);
Получение текущего угла:
const angle = view.getRotation();
Внутренне OpenLayers применяет аффинные преобразования к canvas/WebGL контексту, сохраняя географические координаты неизменными и вращая только визуальное представление.
Вращение нормализуется внутри диапазона [-2π, 2π],
однако логически удобнее работать в пределах [-π, π]. Это
особенно важно при вычислениях пользовательского взаимодействия.
function normalizeRotation(angle) {
return ((angle + Math.PI) % (2 * Math.PI)) - Math.PI;
}
Такая нормализация применяется при обработке жестов и анимаций, чтобы избежать скачков при переходе через границу 360°.
Интеракция DragRotate позволяет вращать карту при
зажатой модифицирующей клавише (по умолчанию Alt + левый
клик мыши).
import DragRotate from 'ol/interaction/DragRotate';
const dragRotate = new DragRotate();
map.addInteraction(dragRotate);
Механика работы основана на вычислении угла между предыдущей и текущей позицией курсора относительно центра карты. Этот угол преобразуется в дельту вращения.
Основные характеристики:
Для сенсорных устройств используется PinchRotate,
реализующий вращение двумя пальцами.
import PinchRotate from 'ol/interaction/PinchRotate';
const pinchRotate = new PinchRotate();
map.addInteraction(pinchRotate);
Алгоритм основан на вычислении угла между двумя векторами касаний. Изменение угла между пальцами интерпретируется как поворот карты.
Ключевые особенности:
UI-компонент вращения реализуется через
ol/control/Rotate. Он предоставляет кнопку сброса вращения
или плавного возврата к нулевому углу.
import Rotate from 'ol/control/Rotate';
const rotateControl = new Rotate({
autoHide: false,
label: '↻',
resetNorth: () => {
view.animate({
rotation: 0,
duration: 300
});
}
});
map.addControl(rotateControl);
Поведение по умолчанию:
Плавное вращение реализуется через механизм
view.animate, использующий интерполяцию значений.
view.animate({
rotation: Math.PI,
duration: 1000
});
Анимация работает через линейную или easing-интерполяцию, обеспечивая непрерывное изменение угла. При этом учитывается кратчайший путь вращения (по часовой или против часовой стрелки).
Изменение угла поворота сопровождается событием
change:rotation.
view.on('change:rotation', () => {
const current = view.getRotation();
});
Дополнительно доступно событие propertychange,
позволяющее отслеживать любые изменения состояния View.
Вращение не изменяет географическую проекцию, но влияет на экранные координаты. Все вычисления пересчёта выполняются через матрицу преобразования:
Это критично для корректной работы взаимодействий, таких как:
В OpenLayers взаимодействия комбинируются, что позволяет создавать сложные жесты:
DragPan + DragRotateMouseWheelZoom + фиксированный rotationPinchZoom + PinchRotateКонфликты жестов решаются через приоритеты интеракций и условия активации (например, модификатор клавиши).
Для предотвращения неконтролируемого вращения применяются ограничения:
import {defaults as defaultInteractions} from 'ol/interaction';
const map = new Map({
interactions: defaultInteractions({
altShiftDragRotate: false,
pinchRotate: true
})
});
Отключение или настройка стандартных интеракций позволяет контролировать UX, особенно в приложениях навигационного типа.
Вращение карты приводит к перерасчёту всей сцены рендеринга. Производительность зависит от:
WebGL-рендерер значительно снижает стоимость поворота за счёт аппаратного ускорения, тогда как Canvas требует перерисовки каждого слоя.
В сложных приложениях угол вращения часто синхронизируется с внешним состоянием:
view.on('change:rotation', () => {
const state = {
rotation: view.getRotation()
};
});
Такой подход используется для:
При активном вращении координаты курсора требуют обратного преобразования:
map.getEventCoordinate(event);
Внутри выполняется:
Это обеспечивает корректную работу интерактивных инструментов независимо от угла поворота.