事件学习
Cesium 的事件系统允许开发者监听和响应场景中的各类交互与状态变化,涵盖 相机操作、实体交互、屏幕输入 等核心场景
屏幕空间事件
屏幕空间事件是最常用的事件类型,用于处理用户在屏幕上的交互操作,如鼠标点击、移动、悬停等,使用 new Cesium.ScreenSpaceEventHandler(element)
,ScreenSpaceEventHandler 传送门
鼠标交互事件
js
viewer.screenSpaceEventHandler.setInputAction(action, type, modifier);
- action: 回调函数, 事件触发后执行的操作
- type: 事件类型, 如鼠标左键点击, 鼠标移动等
- modifier: 键盘事件修饰符, 如 shift, ctrl, alt 等
名字 | 类型 | 描述 |
---|---|---|
LEFT_DOWN | number | 表示鼠标左键按下事件。 |
LEFT_UP | number | 表示鼠标左键松开事件。 |
LEFT_CLICK | number | 表示鼠标左键单击事件。 |
LEFT_DOUBLE_CLICK | number | 表示鼠标左键双击事件。 |
RIGHT_DOWN | number | 表示鼠标右键按下事件。 |
RIGHT_UP | number | 表示鼠标右键松开事件。 |
RIGHT_CLICK | number | 表示鼠标右键单击事件。 |
MIDDLE_DOWN | number | 表示鼠标中键按下事件。 |
MIDDLE_UP | number | 表示鼠标中键松开事件。 |
MIDDLE_CLICK | number | 表示鼠标中键单击事件。 |
MOUSE_MOVE | number | 表示鼠标移动事件。 |
WHEEL | number | 表示鼠标滚轮事件。 |
PINCH_START | number | 表示触摸表面上双指事件的开始。 |
PINCH_END | number | 表示触摸表面上双指事件的结束。 |
PINCH_MOVE | number | 表示触摸表面上双指事件的更改。 |
举一个鼠标左键点击获取经纬度的案例:
js
// 添加地图点击事件, 点击后获取点击位置的经纬度
viewer.screenSpaceEventHandler.setInputAction(function (e) {
// 点击后获取点击位置的笛卡尔坐标
const cartesian = viewer.scene.pickPosition(e.position);
// 笛卡尔坐标转弧度坐标
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
// 弧度转度数
var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
var heightString = cartographic.height;
console.log(
"Longitude: " +
longitudeString +
", Latitude: " +
latitudeString +
", Height: " +
heightString
);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
销毁事件:
js
viewer.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK
);
- 如何判断点击到了实体和获取实体的信息,实体的属性可参考实体
- 添加实体,并定位到实体
js
// 添加实体
const circle = viewer.entities.add({
id: "circle",
name: "circle",
description: "This is circle",
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
ellipse: {
semiMajorAxis: 1000,
semiMinorAxis: 1000,
material: Cesium.Color.RED.withAlpha(0.5),
outline: true,
outlineColor: Cesium.Color.WHITE,
},
});
// 定位到实体
viewer.zoomTo(circle);
- 添加鼠标点击事件,判断点击到了实体,并获取实体的信息
js
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (e) {
// 使用scene.pick方法获取点击位置的实体
const pickedObject = viewer.scene.pick(e.position);
if (
Cesium.defined(pickedObject) &&
pickedObject.id instanceof Cesium.Entity
) {
const entity = pickedObject.id;
console.log("实体信息:", entity); // 输出实体信息
} else {
console.log("未点击到实体");
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
键盘事件
键盘修饰符不可以单独使用,需要配合鼠标输入事件使用
如需监听单个键盘事件,可使用原生的
document.addEventListener("keydown", function (event) {});
,参考相机自由移动案例
名字 | 描述 |
---|---|
SHIFT | 表示 shift 键被按住 |
CTRL | 表示 ctrl 键被按住 |
ALT | 表示 alt 键被按住 |
js
viewer.screenSpaceEventHandler.setInputAction(
function (e) {
console.log("同时按住Shift + 鼠标左键");
},
Cesium.ScreenSpaceEventType.LEFT_CLICK,
Cesium.KeyboardEventModifier.SHIFT
);
相机事件
相机事件(如 RIGHT_DRAG 和 WHEEL)用于控制场景的交互行为(如旋转、缩放、倾斜)
事件类型与默认行为
注: 默认行为通过 ScreenSpaceCameraController 控制
事件类型 | 默认操作 | 适用视图模式 |
---|---|---|
CameraEventType.LEFT_DRAG | 旋转地球(3D)或平移(2D) | 3D/Columbus |
CameraEventType.RIGHT_DRAG | 缩放 | 所有模式 |
CameraEventType.MIDDLE_DRAG | 倾斜地球 | 3D/Columbus |
CameraEventType.WHEEL | 缩放 | 所有模式 |
CameraEventType.PINCH | 缩放/倾斜(触摸屏) | 所有模式 |
js
// cesium 默认事件类型
viewer.scene.screenSpaceCameraController.tiltEventTypes = [
Cesium.CameraEventType.RIGHT_DRAG,
Cesium.CameraEventType.PINCH,
{
eventType: Cesium.CameraEventType.LEFT_DRAG,
modifier: Cesium.KeyboardEventModifier.CTRL,
},
{
eventType: Cesium.CameraEventType.RIGHT_DRAG,
modifier: Cesium.KeyboardEventModifier.CTRL,
},
];
// 设置默认的缩放事件类型
viewer.scene.screenSpaceCameraController.zoomEventTypes = [
Cesium.CameraEventType.MIDDLE_DRAG,
Cesium.CameraEventType.WHEEL,
Cesium.CameraEventType.PINCH,
];
修改默认事件类型
通过覆盖 ScreenSpaceCameraController 的属性,自定义事件映射
属性名 | 属性描述 |
---|---|
lookEventTypes | 3D 视图、2.5D 视图改变相机观察方向 |
rotateEventTypes | 3D 视图相机绕地球旋转 |
tiltEventTypes | 3D 视图、2.5D 视图倾斜视角 |
translateEventTypes | 2.5D 视图、2D 视图地图上平移 |
zoomEventTypes | 地图缩放 |
js
const controller = viewer.scene.screenSpaceCameraController;
// 示例:将右键拖拽改为旋转(默认是缩放)
controller.rotateEventTypes = [Cesium.CameraEventType.RIGHT_DRAG];
// 示例:仅用滚轮控制缩放
controller.zoomEventTypes = [Cesium.CameraEventType.WHEEL];
禁用所有默认交互
js
const controller = viewer.scene.screenSpaceCameraController;
// 禁用所有默认交互
controller.enableRotate = false;
controller.enableZoom = false;
controller.enableTilt = false;
场景事件
相机触发
名字 | 描述 |
---|---|
moveStart | 获取将在摄像机开始移动时引发的事件 |
moveEnd | 获取当摄像机停止移动时将引发的事件 |
changed | 获取当摄像机位置或方向发生变化时将引发的事件 |
js
// 监听相机移动开始
viewer.camera.moveStart.addEventListener(() => {
console.log("相机开始移动");
});
// 监听相机移动结束、获取相机位置
viewer.camera.moveEnd.addEventListener(() => {
const positionCartographic = viewer.camera.positionCartographic;
let cameraPosition = {};
cameraPosition.y = Number(
Cesium.Math.toDegrees(positionCartographic.latitude).toFixed(6)
);
cameraPosition.x = Number(
Cesium.Math.toDegrees(positionCartographic.longitude).toFixed(6)
);
cameraPosition.z = Number(positionCartographic.height.toFixed(1));
cameraPosition.heading = Number(
Cesium.Math.toDegrees(viewer.camera.heading || -90).toFixed(1)
);
cameraPosition.pitch = Number(
Cesium.Math.toDegrees(viewer.camera.pitch || 0).toFixed(1)
);
cameraPosition.roll = Number(
Cesium.Math.toDegrees(viewer.camera.roll || 0).toFixed(1)
);
console.log("相机位置", cameraPosition);
});
// 监听相机位置或方向发生变化
viewer.camera.changed.addEventListener(() => {
console.log("相机位置或方向发生变化");
});
场景渲染
名字 | 描述 |
---|---|
preUpdate | 获取将在场景更新之前引发的事件 |
postUpdate | 获取将在场景更新之后引发的事件 |
preRender | 获取将在场景渲染之前引发的事件 |
postRender | 获取将在场景渲染之后引发的事件 |
js
// 监听场景更新之前的事件
viewer.scene.preUpdate.addEventListener(() => {
console.log("场景更新之前");
});
// 监听场景更新之后的事件
viewer.scene.postUpdate.addEventListener(() => {
console.log("场景更新之后");
});
// 监听场景渲染之前的事件
viewer.scene.preRender.addEventListener(() => {
console.log("场景渲染之前");
});
// 监听场景渲染之后的事件
viewer.scene.postRender.addEventListener(() => {
console.log("场景渲染之后");
});
自定义事件系统
js
// 创建自定义事件总线
const eventBus = {
events: {},
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach((fn) => fn(data));
}
},
on(event, callback) {
if (!this.events[event]) this.events[event] = [];
this.events[event].push(callback);
},
};
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 在实体点击时触发自定义事件
handler.setInputAction((click) => {
const picked = viewer.scene.pick(click.position);
if (picked && picked.id) {
eventBus.emit("entity-clicked", picked.id);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 监听自定义事件
eventBus.on("entity-clicked", (entity) => {
console.log("实体被点击:", entity.name);
});