Cesium ScreenSpaceEventHandler 深度教程
- 发布时间: 2026-02-27 10:30:52
- 相关标签: cesium screenspaceeventhandler 鼠标事件
- 简介: 你想要深入理解 Cesium 中的 `ScreenSpaceEventHandler` 这个核心类,掌握它如何处理用户交互事件并应用到 Cesium 三维场景开发中,我会从基础概念、核心用法到实战案例,全面讲解这个类的使用方法。
手机扫码查看
一、核心概念理解
ScreenSpaceEventHandler 是 Cesium 中处理屏幕空间用户输入事件的核心类,它可以监听 HTML Canvas 元素(Cesium 地球容器)上的鼠标、触摸等交互行为,并绑定自定义处理函数。
1.1 核心作用
- 监听鼠标(点击、移动、滚轮、按下/松开)、触摸(单点、双点、长按)等事件
- 支持键盘修饰键(Ctrl、Shift、Alt)与鼠标/触摸事件的组合监听
- 统一处理 PC 端鼠标事件和移动端触摸事件,无需单独适配
- 提供事件销毁、移除等生命周期管理方法,避免内存泄漏
1.2 关键属性说明
| 属性 | 作用 | 默认值 |
|---|---|---|
mouseEmulationIgnoreMilliseconds |
触摸事件后禁用鼠标模拟事件的时长 | 800ms |
touchHoldDelayMilliseconds |
触摸长按判定的延迟时长 | 1500ms |
二、基础使用流程
2.1 核心步骤(通用模板)
// 1. 获取Cesium容器(Canvas元素)
const canvas = viewer.canvas;
// 2. 创建事件处理器实例
const handler = new Cesium.ScreenSpaceEventHandler(canvas);
// 3. 绑定事件处理函数
handler.setInputAction(
(event) => {
// 事件处理逻辑
console.log('事件触发,位置:', event.position);
},
Cesium.ScreenSpaceEventType.LEFT_CLICK, // 事件类型
Cesium.KeyboardEventModifier.CTRL // 可选:键盘修饰键
);
// 4. 销毁处理器(页面卸载/不再需要时)
// 推荐写法:避免重复销毁报错
handler = handler && handler.destroy();
2.2 核心方法详解
(1)setInputAction(绑定事件)
最核心的方法,用于绑定事件类型和处理函数:
// 示例1:监听左键单击
handler.setInputAction(
(event) => {
// event.position 是屏幕笛卡尔坐标(Cartesian2)
const windowPosition = event.position;
// 将屏幕坐标转换为世界坐标(地形/模型表面)
const cartesian = viewer.scene.globe.pick(
viewer.camera.getPickRay(windowPosition),
viewer.scene
);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
console.log('点击位置经纬度:', lon, lat, height);
}
},
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
// 示例2:监听Shift+右键单击
handler.setInputAction(
(event) => {
console.log('Shift+右键单击触发');
},
Cesium.ScreenSpaceEventType.RIGHT_CLICK,
Cesium.KeyboardEventModifier.SHIFT
);
(2)removeInputAction(移除事件)
移除已绑定的事件处理函数:
// 移除左键单击事件
handler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
// 移除带修饰键的事件
handler.removeInputAction(
Cesium.ScreenSpaceEventType.RIGHT_CLICK,
Cesium.KeyboardEventModifier.SHIFT
);
(3)getInputAction(获取绑定的事件函数)
const clickAction = handler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
if (clickAction) {
console.log('已绑定左键单击处理函数');
}
(4)destroy / isDestroyed(销毁/判断销毁状态)
// 安全销毁
if (!handler.isDestroyed()) {
handler.destroy();
}
// 或者简化写法
handler = handler && handler.destroy();
三、常见事件类型与回调参数
3.1 基础事件类型(ScreenSpaceEventType)
| 事件类型 | 触发条件 | 回调参数类型 | 核心参数 |
|---|---|---|---|
LEFT_CLICK |
鼠标左键单击/触摸单点点击 | PositionedEvent | position(Cartesian2) |
LEFT_DOUBLE_CLICK |
鼠标左键双击 | PositionedEvent | position |
LEFT_DOWN |
鼠标左键按下/触摸按下 | PositionedEvent | position |
LEFT_UP |
鼠标左键松开/触摸松开 | PositionedEvent | position |
RIGHT_CLICK |
鼠标右键单击 | PositionedEvent | position |
MIDDLE_CLICK |
鼠标中键单击 | PositionedEvent | position |
MOUSE_MOVE |
鼠标移动/触摸滑动 | MotionEvent | startPosition, endPosition |
WHEEL |
鼠标滚轮滚动 | WheelEvent | delta(滚动值) |
PINCH |
双指缩放 | TwoPointMotionEvent | position1/2, previousPosition1/2 |
3.2 实战案例:双指缩放监听
handler.setInputAction(
(event) => {
// 获取双指当前位置和上一位置
const pos1 = event.position1;
const pos2 = event.position2;
const prevPos1 = event.previousPosition1;
const prevPos2 = event.previousPosition2;
// 计算缩放比例
const currentDistance = Cesium.Cartesian2.distance(pos1, pos2);
const previousDistance = Cesium.Cartesian2.distance(prevPos1, prevPos2);
const scale = currentDistance / previousDistance;
console.log('双指缩放比例:', scale);
// 可根据缩放比例自定义相机行为
viewer.camera.zoomIn((1 - scale) * 100);
},
Cesium.ScreenSpaceEventType.PINCH
);
四、高级应用场景
4.1 场景1:鼠标拾取实体
// 监听鼠标移动,高亮拾取的实体
handler.setInputAction(
(event) => {
// 获取鼠标位置对应的实体
const pickedObject = viewer.scene.pick(event.endPosition);
if (Cesium.defined(pickedObject) && pickedObject.id) {
// 高亮实体(修改样式)
pickedObject.id.color = Cesium.Color.YELLOW;
// 记录上一个高亮的实体,恢复样式
if (window.lastPickedEntity) {
window.lastPickedEntity.color = Cesium.Color.RED;
}
window.lastPickedEntity = pickedObject.id;
} else if (window.lastPickedEntity) {
// 鼠标离开实体,恢复样式
window.lastPickedEntity.color = Cesium.Color.RED;
window.lastPickedEntity = undefined;
}
},
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
4.2 场景2:自定义相机控制
// 监听鼠标拖拽(左键按下+移动)实现自定义平移
let isDragging = false;
let startPosition;
// 监听左键按下
handler.setInputAction(
(event) => {
isDragging = true;
startPosition = event.position;
},
Cesium.ScreenSpaceEventType.LEFT_DOWN
);
// 监听鼠标移动
handler.setInputAction(
(event) => {
if (isDragging) {
const endPosition = event.endPosition;
// 计算鼠标移动偏移量
const deltaX = endPosition.x - startPosition.x;
const deltaY = endPosition.y - startPosition.y;
// 自定义相机平移
viewer.camera.moveRight(-deltaX * 10);
viewer.camera.moveUp(deltaY * 10);
startPosition = endPosition;
}
},
Cesium.ScreenSpaceEventType.MOUSE_MOVE
);
// 监听左键松开
handler.setInputAction(
() => {
isDragging = false;
},
Cesium.ScreenSpaceEventType.LEFT_UP
);
4.3 场景3:触摸长按事件模拟
let touchHoldTimer = null;
// 监听触摸按下
handler.setInputAction(
(event) => {
// 启动长按计时器
touchHoldTimer = setTimeout(() => {
console.log('触摸长按触发,位置:', event.position);
// 执行长按逻辑(如显示弹窗、创建标记等)
viewer.entities.add({
position: viewer.scene.globe.pick(
viewer.camera.getPickRay(event.position),
viewer.scene
),
point: {
pixelSize: 10,
color: Cesium.Color.RED
}
});
}, Cesium.ScreenSpaceEventHandler.touchHoldDelayMilliseconds);
},
Cesium.ScreenSpaceEventType.LEFT_DOWN
);
// 监听触摸松开,清除计时器
handler.setInputAction(
() => {
clearTimeout(touchHoldTimer);
},
Cesium.ScreenSpaceEventType.LEFT_UP
);
五、最佳实践与注意事项
5.1 内存泄漏防范
- 必须销毁处理器:在组件卸载、页面关闭时,调用
destroy()方法 - 避免重复创建:确保同一容器只创建一个
ScreenSpaceEventHandler实例 - 及时移除事件:不再需要的事件,调用
removeInputAction移除
5.2 跨端兼容
- 移动端触摸事件会自动模拟鼠标事件,可通过
mouseEmulationIgnoreMilliseconds调整忽略时长 - 双指操作(缩放、旋转)优先使用
PINCH/TWIST事件,而非自定义计算
5.3 性能优化
- 鼠标移动事件(
MOUSE_MOVE)触发频率高,避免在回调中执行复杂计算 - 可通过节流函数限制高频事件的执行次数:
function throttle(fn, delay) { let lastTime = 0; return (...args) => { const now = Date.now(); if (now - lastTime > delay) { fn(...args); lastTime = now; } }; } // 节流处理鼠标移动事件(每100ms执行一次) handler.setInputAction( throttle((event) => { // 处理逻辑 }, 100), Cesium.ScreenSpaceEventType.MOUSE_MOVE );
总结
关键点回顾
ScreenSpaceEventHandler是 Cesium 处理屏幕交互的核心类,支持鼠标/触摸/键盘组合事件,需绑定到 Canvas 元素使用。- 核心方法是
setInputAction(绑定事件)、removeInputAction(移除事件)、destroy(销毁实例),使用时需注意生命周期管理。 - 不同事件类型对应不同的回调参数结构,可通过屏幕坐标转换实现实体拾取、坐标获取等核心功能,开发时需注意跨端兼容和性能优化。
书签篮