Cesium 点击获取场景 Entity
需求描述:(1)使用 Cesium 构建地形图并且放置了三维模型后,需要实现点击三维模型变换颜色。(2)点击另外一个模型,前一个通过点击变换颜色的模型须将颜色换回来。
解决方案:对于第一个需求,我们使用 Cesium 中 viewer.scene.pick() 获取 entity 后直接更改entity 的 model 属性;对于第二个需求,我们需要利用设置监听函数,获取鼠标左击的地图位置,再通过 viewer.scene.pick() 抓取在该位置的 entity 并对其更改属性。
关键函数介绍
new Cesium.ScreenSpaceEventHandler(canvas)
这没什么好说的,设置监听事件首先需要对画布设置事件监听
ScreenSpaceEventHandler.setInputAction(action, type, modifier)
setInputAction 函数注册事件监听器,函数三个参数(第二个没用过)。第一个参数为回调函数,第三个为事件触发的动作。
viewer.scene.pick(windowPosition)
pick 函数接受一个 Cartesian2 的对象表示鼠标所在的屏幕位置,函数用于拾取将鼠标位置所代表的地理坐标的对象,主要有:Entity(实体)、Primitive(基元)、Tileset(瓦片集)等等。如果点击空白或者地形图等,则会返回 undefine
viewer.entities.getById(id)/EntityCollection.getById(id)
getById 函数接受一个参数 id,该函数用来实现通过 entity 的 id 属性寻找对应的实体。
代码展示
//点击模型获取信息并且更换模型
let colored_entity_id = 0; //记录换颜色的模型id
var handler_1 = new Cesium.ScreenSpaceEventHandler(canvas);
handler_1.setInputAction(function(movement){
var pick = viewer.scene.pick(movement.position);//拾取鼠标所在的entity
if (Cesium.defined(pick)) {
var colored_entity = viewer.entities.getById(colored_entity_id);//查看是否已有换颜色的模型
if(Cesium.defined(colored_entity))//如果有,先将换颜色的模型换回来,在把当前模型换色
{
colored_entity.model.uri = "/1.glb";
pick.id.model.uri = "/2.glb";
colored_entity_id = pick.id.id;
}else{//如果没有,直接把当前模型换色
pick.id.model.uri = "/2.glb";
//this.former_id = pick.id;
colored_entity_id = pick.id.id;
}
}
},Cesium.ScreenSpaceEventType.LEFT_CLICK)
问题
吐槽一句,viewer.scene.pick() 你是珍妮嘛坑啊!!!!!
原本以为 viewer.scene.pick() 和 viewer.entities.getById() 都会返回 entity 对象,于是我的原先的代码是这么写的。
if(Cesium.defined(colored_entity))
{
colored_entity.model.uri = "/1.glb";
pick.model.uri = "/2.glb";
colored_entity_id = pick.id;
}else{
pick.model.uri = "/2.glb";
colored_entity_id = pick.id;
}
一直失败,后来我去查了一下文档发现两个函数是这么定义的:
我发现,viewer.entities.getById() 返回的是 entity,但是 viewer.scene.pick() 返回的是一个 object 的东西,文档解释这个 object 包含了 primitives 的特征,那既然如此我就不能像直接访问 entity.id 的形式去访问这个 object 的 id 了。通过调试我发现,果然!entity.model.uri 不可以,entity.id.model.uri 才可以;pick.id 不可以,pick.id.id 才可以😭😭😭😭