图层组
某天领导找我,说业务中可能存在多个影像服务为一个图层组,并且需要同时加载和同时在图层列表中上下移动的需求。
例如一些专题地图,包含所有学校、医院、公交站等图层,而这些图层都是单独发布的。
在 Cesium 中确实存在一个图层组 ImageryLayerCollection 。但是可以发现 ImageryLayerCollection 和 PrimitiveCollection 不同,虽然两者都会在 Cesium 初始化时创建一个默认的对象,但是 PrimitiveCollection 可以嵌套使用而 ImageryLayerCollection 不行。
Cesium 不能添加图层组其实对同时加载多个图层影响不大,但是如果需要在图层树中移动位置,就比较复杂了。领导说项目人员很头疼,速速解决。
实现思路
既然原生的 ImageryLayerCollection 只接受 ImageryLayer 作为子对象。那写一个能够管理多个服务的 ImageryLayer 不就行了吗。
为了不动 Cesium 源码,可以直接拷贝一份 ImageryLayer.js 到外面修改实现图层组。
其实 ImageryLayer.js 中做的东西并不算复杂,上级的地形四叉树在渲染时,会为每块地形瓦片查找他的贴图(附着在地形上的影像),这一步操作最终会进入到 _createTileImagerySkeletons 方法,然后就是请求瓦片和判断是否需要重投影的操作。具体可以参考最复杂的地球皮肤 影像与地形的渲染与下载过程
只是 ImageryLayer.js 中只对一个 imageryProvider 进行管理和操作。那需要做的其实只是把管理一个 imageryProvider 改成管理多个而已。
成果检验
测试代码中创建了三个图层。为了测试对不同 imageryProvider 的统一管理是否能够成功实现,因此特地混用了影像服务的切片方案。
bingMapsAerialWithLabels 切片方案为 WebMercatorTilingScheme 而 其余两个服务切片方案为 GeographicTilingScheme。
观察 viewer.scene.imageryLayers 中的内容可以发现,成功使用一个 imageryLayer 加载了三个服务
继续拓展
由于目前图层组管理的是多个imageryProvider,而不是多个 imageryLayer, 因此实际上只能做到一层嵌套,也就是图层组里面只能放图层,而不能放图层组。
由于目前已经能满足项目需求,因此就懒得再搞下去了😅
其实要解决也简单,再封装一个管理 ImageryLayer 的 ImageryLayer 就行了。
原文链接
Cesium中实现图层组