在应用基于 Cesium 的 Mars3D 第三方库做开发的时候,碰到了这么一个需要:“实现两个模型之间的连线,这个直线能够随着模型的挪动而挪动”。
Mars3D 中提供了一个标绘性能,简略来说就是能够通过拖动鼠标扭转模型在图层上的地位。所以提出的需要就简化成了————“鼠标拖动模型,模型间的连线随着模型挪动而挪动”。
这里模型的挪动形式对于后续的计划解决有很大的影响。首先我来讲讲第一种计划失败的可能起因。
计划一(失败)
model 的 position 应用 PositionProperty, polyline 的 position 应用 PositionPropertyArray,array 数组外面是 ReferenceProperty, 这里是为了让 polyline 两端的地位依赖于模型的地位。
这种计划是能够胜利显示出连线的,然而问题出在标绘上。
调用提供的标绘函数的时候,会呈现如图的谬误
在 ReferenceProperty 的 api 文档中提到了只有援用的属性是 PositionProperty 是这个函数才无效。
然而咱们在最后设定模型 position 的时候的确是应用的 PositionProperty,这里我猜测应该是标绘函数应用了一个 CallbackProperty,回调的 Object 不再是 PositionProperty 类型了,因而会出错。Mars3D 的 api 并没有开源,具体起因也无从得悉了。
计划二(胜利)
既然咱们想用 Mars3D 的 api 实现咱们的需要,就须要另辟蹊径。
第二种计划应用了 czml 数据格式,czml 数据配置项中的 polyline/position 属性有一个 references 选项,应用它也能够实现地位依赖。
"polyline":{
"positions":{
"references":[
"model1#position",
"model2#position"
]
}
}
新的问题便是:怎么引入这个 czml 数据?
Mars3D 中提供了很多图层,这些图层都具备不同的性能。咱们上文中提到的标绘性能,是基于 graphicLayer 的,然而 graphicLayer 并不反对导入 czml,Mars3D 独自提供了 czmlLayer 能够导入 czml 配置文件。
因而采纳“双图层同步”的解决方案:graphicLayer 上的标绘扭转模型地位后,应用监听事件获取扭转后的模型坐标,同步更新 czml 配置文件的相应模型的 position 属性内容,并更新 czmlLayer 图层。
graphicLayer 显示模型,czmlLayer 中的配置项中仅仅记录模型的地位,不显示模型,只显示 polyline。简略来说,graphicLayer 上的模型和 czmlLayer 的模型实际上是两个独自的实体,只是通过监听事件让这它们的地位时刻保持一致。
// 模型绑定监听事件
this.graphicLayer.getGraphicById("Firecar").on(mars3d.EventType.updatePosition,function (event){//console.log("地位产生了变动!",event)
console.log(event.position.getValue(Cesium.JulianDate.fromDate(new Date('2022-06-16 08:00:00'))))
that.czml.forEach(function(value,index,array){if(value.id ==='Firecar')
value.position = {"cartographicDegrees": (mars3d.LngLatPoint.fromCartesian(event.position.getValue(Cesium.JulianDate.fromDate(new Date('2022-06-16 08:00:00'))))).toArray(false)
}
});
// 更新 czml 图层
that.czmlLayer.load()
console.log(that.czmlLayer)
})
须要留神的点:监听事件返回的是一个 event,event 外面有监听的 position 属性,这个属性是一个 callbackProperty,应用 getValue 办法传入轻易一个工夫值得到变动后的坐标,留神失去的这个坐标是 cartesian3,更新 czml 时候要将 cartesian3 换成 array,这样直线才会失常显示。
这里的代码只是示意,目标还是为了分享解决思路。