Cesium快速入门到精通系列教程二十:Cesium 1.95 给实体添加事件
一、给Entity创建的实体添加事件
1、常用 Entity 事件类型
Cesium 的 Entity支持通过 viewer.entities添加多个实体,每个实体都可以监听以下类型的事件:
事件名称 | 触发时机 |
---|---|
| 鼠标左键单击该实体时触发 |
| 鼠标左键双击该实体时触发 |
| 鼠标移入该实体时触发 |
| 鼠标移出该实体时触发 |
| 鼠标在该实体上移动时触发 |
| 鼠标右键点击该实体时触发 |
注意:这些事件是由 ScreenSpaceEventHandler 在底层支持的,但 Cesium 对 Entity 进行了封装,让你可以直接为每个 entity 绑定事件。
2、如何给 Entity 添加事件
示例:给一个 Entity 添加 click 事件
// 创建 viewer
const viewer = new Cesium.Viewer('cesiumContainer');// 添加一个 Entity(比如一个点)
const entity = viewer.entities.add({name: '测试点',position: Cesium.Cartesian3.fromDegrees(116.39, 39.9), // 北京大致经纬度point: {pixelSize: 10,color: Cesium.Color.YELLOW},label: {text: '点击我',font: '14pt sans-serif',fillColor: Cesium.Color.WHITE,outlineColor: Cesium.Color.BLACK,outlineWidth: 2,style: Cesium.LabelStyle.FILL_AND_OUTLINE,pixelOffset: new Cesium.Cartesian2(0, -40)}
});// 为该 Entity 添加 click 事件
viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(function onEntityClick(event) {const pickedObject = viewer.scene.pick(event.position);if (Cesium.defined(pickedObject) && pickedObject.id === entity) {console.log('你点击了实体:', pickedObject.id.name); // 输出实体名称alert('你点击了:' + pickedObject.id.name);}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
🔍 说明:
我们使用 viewer.scene.pick(position)来获取当前鼠标点击位置所对应的对象(pickedObject)。
然后判断 pickedObject.id是否是我们关心的那个 entity,如果是,则说明用户点击了这个实体。
pickedObject.id就是该 entity 对象本身,所以你可以访问 pickedObject.id.name或其他属性。
总结
能否直接用 | ❌ 不可以,Cesium 1.95 的 Entity 没有直接的 on 方法 |
---|---|
如何给 Entity 添加事件? | 通过 |
推荐做法 | 封装一个函数,传入 entity 和回调,内部做 pick 判断 |
支持哪些事件? | click, doubleClick, mousemove, mouseover, mouseout, rightclick 等,但需通过 pick 判断目标 |
二、给new Cesium.*Collection()创建的实体添加事件
以new Cesium.BillboardCollection()为例展示如何:
- 使用 BillboardCollection创建多个 Billboard;
- 为每个 Billboard 关联自定义数据(比如 id 或信息对象);
- 使用 ScreenSpaceEventHandler监听点击事件;
- 判断用户点击的是否为某个 Billboard;
- 如果是,弹窗显示该 Billboard 的信息。
完整代码:
const billboardCollection = new Cesium.BillboardCollection();viewer.scene.primitives.add(billboardCollection);const billboardMap = new Map();const position1 = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0);const billboard1 = billboardCollection.add({id: "billboard_001",position: position1,image: "/icon/car1.png",scale: 1.0,rotation: Cesium.Math.toRadians(45), // 设置角度});const customId1 = "billboard_001";billboardMap.set(customId1, billboard1);const position2 = Cesium.Cartesian3.fromDegrees(121.47, 31.23, 0);const billboard2 = billboardCollection.add({id: "billboard_002",position: position2,image: "/icon/car2.png",scale: 1.0,rotation: Cesium.Math.toRadians(45), // 设置角度});const customId2 = "billboard_002";billboardMap.set(customId2, billboard2);// 监听点击事件const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function onClick(event) {const pickedObject = viewer.scene.pick(event.position);if (Cesium.defined(pickedObject) && pickedObject.id && billboardMap.has(pickedObject.id)) {// 检查 pickedObject 是否是我们添加的 billboardconst info = billboardMap.get(pickedObject.id);alert("你点击了这个 Billboard(通过 Primitive 拾取)");} else {alert('未点击到任何 Billboard 或点击了其他对象');}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
🔍 关键点解释
1、创建实体时一定要手动设置id;
const billboard1 = billboardCollection.add({id: "billboard_001", // 手动设置idposition: position1,image: "/icon/car1.png",scale: 1.0,rotation: Cesium.Math.toRadians(45), // 设置角度});
2、维护 Billboard 与数据的映射
- 使用 Map或普通对象来保存 billboard.id -> 信息对象的映射关系。
- 这样当你通过 pick拿到 id后,就能查询到对应的数据。
3、如何判断点击的是哪个 Billboard?
- 使用 viewer.scene.pick(event.position)可以获取鼠标点击位置的对象。
- 如果返回的 pickedObject有 id属性,并且这个 id存在于你维护的 billboardDataMap中,说明点击的是你添加的 Billboard。
- 你可以通过 billboardDataMap.get(pickedObject.id)获取该 Billboard 的相关信息。
实例:给当前点击的实体添加一个瞄准图标
let currentAimBillboard = null; // 当前显示的瞄准广告牌const billboardCollection = new Cesium.BillboardCollection();viewer.scene.primitives.add(billboardCollection);const billboardMap = new Map();const position1 = Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0);const billboard1 = billboardCollection.add({id: "billboard_001",position: position1,image: "/icon/car1.png",scale: 1.0,rotation: Cesium.Math.toRadians(45), // 设置角度});const customId1 = "billboard_001";billboardMap.set(customId1, billboard1);const position2 = Cesium.Cartesian3.fromDegrees(121.47, 31.23, 0);const billboard2 = billboardCollection.add({id: "billboard_002",position: position2,image: "/icon/car2.png",scale: 1.0,rotation: Cesium.Math.toRadians(45), // 设置角度});const customId2 = "billboard_002";billboardMap.set(customId2, billboard2);// 监听点击事件const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function onClick(event) {const pickedObject = viewer.scene.pick(event.position);if (Cesium.defined(pickedObject) &&pickedObject.id &&billboardMap.has(pickedObject.id)) {// 如果之前有瞄准图标,先移除它if (currentAimBillboard) {billboardCollection.remove(currentAimBillboard);}// 在点击的 billboard 的位置上添加一个“瞄准”图标currentAimBillboard = billboardCollection.add({position: billboardMap.get(pickedObject.id).position,image: "/icon/aim.png", // 替换为真实的瞄准图片,比如准星width: 64,height: 64,});} else {if (currentAimBillboard) {billboardCollection.remove(currentAimBillboard);} // 点击其它位置时清除掉瞄准图标}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
思路:
1、点击实体时,如果currentAimBillboard不为空,则先清空再在当前实体位置添加瞄准图标;
2、点击实体以外的部分时,如果currentAimBillboard不为空,则清空。