ScreenSpaceEventHandler — один из ключевых механизмов
взаимодействия пользователя со сценой в CesiumJS. Класс предназначен для
обработки событий ввода, происходящих внутри HTML-элемента, связанного с
визуализацией карты или глобуса. С его помощью реализуются реакции на
щелчки мыши, перемещение курсора, двойные клики, использование колеса
прокрутки, касания на сенсорных устройствах и различные комбинации
клавиш-модификаторов.
Практически любой интерактивный инструмент в CesiumJS — выбор
объектов, отображение информации по клику, измерение расстояний,
рисование геометрии, перемещение сущностей — строится на основе
ScreenSpaceEventHandler.
Обычно обработчик создаётся для канваса (canvas) объекта
Viewer.
const viewer = new Cesium.Viewer("cesiumContainer");
const handler = new Cesium.ScreenSpaceEventHandler(
viewer.scene.canvas
);
После создания объект начинает отслеживать пользовательские действия внутри указанного элемента.
Обработка событий строится на трёх основных компонентах:
ScreenSpaceEventHandler.ScreenSpaceEventType).Общая схема выглядит следующим образом:
handler.setInputAction(
function(event) {
console.log(event);
},
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
Когда происходит событие LEFT_CLICK, вызывается
переданная функция.
Cesium предоставляет набор предопределённых типов событий.
Обычный щелчок левой кнопкой мыши.
handler.setInputAction(function(event) {
console.log("Левый клик");
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Двойной щелчок левой кнопкой.
handler.setInputAction(function(event) {
console.log("Двойной клик");
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
По умолчанию Cesium использует двойной клик для приближения камеры к выбранной точке сцены.
Нажатие левой кнопки мыши.
handler.setInputAction(function(event) {
console.log("Кнопка нажата");
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
Событие возникает сразу после нажатия.
Отпускание левой кнопки.
handler.setInputAction(function(event) {
console.log("Кнопка отпущена");
}, Cesium.ScreenSpaceEventType.LEFT_UP);
Щелчок правой кнопкой мыши.
handler.setInputAction(function(event) {
console.log("Правый клик");
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
События нажатия и отпускания правой кнопки.
handler.setInputAction(function(event) {
console.log("Правая кнопка нажата");
}, Cesium.ScreenSpaceEventType.RIGHT_DOWN);
handler.setInputAction(function(event) {
console.log("Правая кнопка отпущена");
}, Cesium.ScreenSpaceEventType.RIGHT_UP);
Щелчок средней кнопкой мыши.
handler.setInputAction(function(event) {
console.log("Средняя кнопка");
}, Cesium.ScreenSpaceEventType.MIDDLE_CLICK);
Нажатие и отпускание средней кнопки.
handler.setInputAction(function(event) {
console.log("Средняя кнопка нажата");
}, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);
Перемещение курсора.
Одно из наиболее часто используемых событий.
handler.setInputAction(function(event) {
console.log(event.endPosition);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
Используется для:
Прокрутка колеса мыши.
handler.setInputAction(function(delta) {
console.log(delta);
}, Cesium.ScreenSpaceEventType.WHEEL);
Событие позволяет реализовывать собственную логику масштабирования или изменения параметров интерфейса.
Начало жеста масштабирования на сенсорном устройстве.
handler.setInputAction(function(event) {
console.log("Начало pinch");
}, Cesium.ScreenSpaceEventType.PINCH_START);
Изменение масштаба во время жеста.
handler.setInputAction(function(event) {
console.log("Pinch move");
}, Cesium.ScreenSpaceEventType.PINCH_MOVE);
Завершение жеста.
handler.setInputAction(function(event) {
console.log("Pinch end");
}, Cesium.ScreenSpaceEventType.PINCH_END);
Тип передаваемого объекта зависит от конкретного события.
Используется для одиночных кликов.
Структура:
{
position: Cartesian2
}
Пример:
handler.setInputAction(function(event) {
console.log(event.position.x);
console.log(event.position.y);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Используется для движения курсора.
Структура:
{
startPosition: Cartesian2,
endPosition: Cartesian2
}
Пример:
handler.setInputAction(function(event) {
console.log(event.startPosition);
console.log(event.endPosition);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
Применяется для мультитач-событий.
Структура содержит позиции двух касаний.
{
position1,
position2
}
Используется при работе с жестами масштабирования и вращения.
Одно из самых распространённых применений — определение географических координат.
handler.setInputAction(function(event) {
const cartesian =
viewer.camera.pickEllipsoid(
event.position
);
if (cartesian) {
const cartographic =
Cesium.Cartographic.fromCartesian(
cartesian
);
const longitude =
Cesium.Math.toDegrees(
cartographic.longitude
);
const latitude =
Cesium.Math.toDegrees(
cartographic.latitude
);
console.log(latitude, longitude);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Метод работает только относительно поверхности земного эллипсоида.
Если используется Terrain, рекомендуется применять
pickPosition.
handler.setInputAction(function(event) {
const cartesian =
viewer.scene.pickPosition(
event.position
);
console.log(cartesian);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Такой подход позволяет получать реальные координаты поверхности, включая высоту.
Для определения объекта под курсором используется метод
scene.pick().
handler.setInputAction(function(event) {
const pickedObject =
viewer.scene.pick(
event.position
);
console.log(pickedObject);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(function(event) {
const picked =
viewer.scene.pick(
event.position
);
if (Cesium.defined(picked)) {
console.log(picked.id);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Если объект был создан через API сущностей, его можно получить через
свойство id.
Типичный сценарий взаимодействия — выделение объекта под курсором.
let highlighted;
handler.setInputAction(function(event) {
const picked =
viewer.scene.pick(
event.endPosition
);
if (
Cesium.defined(picked) &&
picked.id
) {
if (
highlighted &&
highlighted !== picked.id
) {
highlighted.point.color =
Cesium.Color.WHITE;
}
highlighted = picked.id;
highlighted.point.color =
Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
Подобная логика широко применяется в геоинформационных системах.
let selected = null;
handler.setInputAction(function(event) {
const picked =
viewer.scene.pick(
event.position
);
if (
Cesium.defined(picked)
) {
selected = picked.id;
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
handler.setInputAction(function(event) {
if (!selected) {
return;
}
const position =
viewer.camera.pickEllipsoid(
event.endPosition
);
if (position) {
selected.position = position;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction(function() {
selected = null;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
Обработчики могут реагировать только при зажатых клавишах.
Доступны:
handler.setInputAction(
function(event) {
console.log("Shift + Click");
},
Cesium.ScreenSpaceEventType.LEFT_CLICK,
Cesium.KeyboardEventModifier.SHIFT
);
handler.setInputAction(
function(event) {
console.log("Ctrl + Click");
},
Cesium.ScreenSpaceEventType.LEFT_CLICK,
Cesium.KeyboardEventModifier.CTRL
);
handler.setInputAction(
function(event) {
console.log("Alt + Click");
},
Cesium.ScreenSpaceEventType.LEFT_CLICK,
Cesium.KeyboardEventModifier.ALT
);
Если для одного события вызывается setInputAction()
повторно, предыдущий обработчик заменяется.
handler.setInputAction(firstHandler,
Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler.setInputAction(secondHandler,
Cesium.ScreenSpaceEventType.LEFT_CLICK);
После выполнения второго вызова будет работать только
secondHandler.
Для чтения зарегистрированного обработчика используется метод
getInputAction().
const callback =
handler.getInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
Это позволяет временно сохранять стандартную логику Cesium и затем восстанавливать её.
Для удаления используется removeInputAction().
handler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
После удаления событие больше не будет обрабатываться.
При уничтожении инструмента или компонента обработчик рекомендуется удалять.
handler.destroy();
Проверка состояния:
if (!handler.isDestroyed()) {
handler.destroy();
}
После вызова destroy() экземпляр становится непригодным
для дальнейшего использования.
Многие действия камеры в Cesium реализованы через собственные обработчики событий.
Например, можно отключить масштабирование двойным кликом.
viewer.cesiumWidget.screenSpaceEventHandler
.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
После удаления обработчика двойной щелчок перестанет изменять положение камеры.
Допускается создание нескольких экземпляров
ScreenSpaceEventHandler.
const selectionHandler =
new Cesium.ScreenSpaceEventHandler(
viewer.scene.canvas
);
const drawingHandler =
new Cesium.ScreenSpaceEventHandler(
viewer.scene.canvas
);
Однако большое количество параллельных обработчиков усложняет управление событиями. В большинстве приложений предпочтительнее использовать один экземпляр и переключать режимы работы через внутреннее состояние инструмента.
Типичный алгоритм работы через
ScreenSpaceEventHandler:
Пример регистрации событий:
handler.setInputAction(
addPoint,
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
handler.setInputAction(
updatePreview,
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
handler.setInputAction(
cancelMeasurement,
Cesium.ScreenSpaceEventType.RIGHT_CLICK
);
Подобная схема лежит в основе большинства интерактивных инструментов ГИС-приложений.
Неверно:
const picked =
viewer.scene.pick(
event.position
);
console.log(picked.id);
Правильно:
const picked =
viewer.scene.pick(
event.position
);
if (Cesium.defined(picked)) {
console.log(picked.id);
}
Неверно:
handler.destroy();
handler.setInputAction(...);
После уничтожения объект необходимо создавать заново.
При создании временных инструментов необходимо удалять события:
handler.removeInputAction(
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
или полностью уничтожать экземпляр:
handler.destroy();
Иначе возможны утечки памяти и накопление лишней логики обработки.
ScreenSpaceEventHandler используется практически во всех
интерактивных возможностях CesiumJS:
Благодаря единому механизму обработки мыши, клавиатурных
модификаторов и сенсорных жестов класс
ScreenSpaceEventHandler выступает центральным элементом
пользовательского взаимодействия со сценой CesiumJS и является
фундаментом для разработки сложных интерактивных приложений на основе
трёхмерной геовизуализации.