Skip to content

事件学习

Cesium 的事件系统允许开发者监听和响应场景中的各类交互与状态变化,涵盖 相机操作、实体交互、屏幕输入 等核心场景

屏幕空间事件

屏幕空间事件是最常用的事件类型,用于处理用户在屏幕上的交互操作,如鼠标点击、移动、悬停等,使用 new Cesium.ScreenSpaceEventHandler(element),ScreenSpaceEventHandler 传送门

鼠标交互事件

js
viewer.screenSpaceEventHandler.setInputAction(action, type, modifier);
  • action: 回调函数, 事件触发后执行的操作
  • type: 事件类型, 如鼠标左键点击, 鼠标移动等
  • modifier: 键盘事件修饰符, 如 shift, ctrl, alt 等
名字类型描述
LEFT_DOWNnumber表示鼠标左键按下事件。
LEFT_UPnumber表示鼠标左键松开事件。
LEFT_CLICKnumber表示鼠标左键单击事件。
LEFT_DOUBLE_CLICKnumber表示鼠标左键双击事件。
RIGHT_DOWNnumber表示鼠标右键按下事件。
RIGHT_UPnumber表示鼠标右键松开事件。
RIGHT_CLICKnumber表示鼠标右键单击事件。
MIDDLE_DOWNnumber表示鼠标中键按下事件。
MIDDLE_UPnumber表示鼠标中键松开事件。
MIDDLE_CLICKnumber表示鼠标中键单击事件。
MOUSE_MOVEnumber表示鼠标移动事件。
WHEELnumber表示鼠标滚轮事件。
PINCH_STARTnumber表示触摸表面上双指事件的开始。
PINCH_ENDnumber表示触摸表面上双指事件的结束。
PINCH_MOVEnumber表示触摸表面上双指事件的更改。

举一个鼠标左键点击获取经纬度的案例:

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
);
  • 如何判断点击到了实体和获取实体的信息,实体的属性可参考实体
  1. 添加实体,并定位到实体
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);
  1. 添加鼠标点击事件,判断点击到了实体,并获取实体的信息
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 的属性,自定义事件映射

属性名属性描述
lookEventTypes3D 视图、2.5D 视图改变相机观察方向
rotateEventTypes3D 视图相机绕地球旋转
tiltEventTypes3D 视图、2.5D 视图倾斜视角
translateEventTypes2.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);
});

参考

事件参考