最近使用Cesium结合ts和react自己手动搭建了一个基本界面,加载3dTiles数据和geojson数据,动态控制图层的显隐。本来以为是非常简单的功能,但是实际操作中发现有一些地方值得注意。

搭建的效果就是这个样子,经典的顶部header+左侧布局,主视窗显示地图:

加载geojson数据源的方法很简单,Cesium.GeoJsonDataSource.load方法会返回
Promise<Cesium.GeoJsonDataSource> 类型的Promise(resolve),给其指定一个固定的标识name。
代码:
const shandongJson = Cesium.GeoJsonDataSource.load( '../mock/shandong.geojson',
{ clampToGround:true } ) shandongJson.then((shandongJson)=>{ shandongJson.name =
'山东'; viewRef.dataSources.add(shandongJson) })
因为有 Cesium.Viewer.dataSources.getByName() 方法,直接通过name属性获取对应的geojson对象。
// 涉及业务代码的部分就不放上了 重点是getByName方法 if (info.node.type === 'geojson' && viewer){
viewer.dataSources.getByName(info.node.title as string)[0].show = info.checked;
}
但是在加载3dTile数据时,就没这么方便了,当我向Viewer中同时添加json数据源和3dTile数据时,通过打印其存储位置,发现是这样的:


在Cesium官网上查阅没有一个可以直接获取Cesium3DTileset对象实例的方法,通过index获取获取实例显然不太可行,没办法,只能想一个其它的方法用来存储Cesium3DTileset对象。于是使用Mobx建立全局store,思路如下,Redux和Vuex也是同理,只是语法不同。
import { action, extendObservable, runInAction } from "mobx"; import * as
Cesiumfrom 'cesium' interface tileSetListProp { [key: string]: Cesium.
Cesium3DTileset} interface OBSERVABLE_PROP { tileSetList: tileSetListProp } //
可观察属性 const OBSERVABLE: OBSERVABLE_PROP = { tileSetList: {}, }; // 建立下面的数据结构存储
// { // key1: Cesium3DTileset1, // key2: Cesium3DTileset2, // } class Tiles {
tileSetList: tileSetListProp = {} constructor() { extendObservable(this, { ...
OBSERVABLE }); } // 向容器中添加新的Cesium3DTileset @action.bound addTileSet = (key:
string, tileSet: Cesium.Cesium3DTileset) => { runInAction(() => { this.
tileSetList[key] = tileSet; }); } @action.bound update(data: any) { Object.
assign(this, data); } } export default new Tiles();
页面加载时:引入全局变量,在数据加载时把它存进去:addTileSet(‘Building’, tileBuilding),
useStores是一个工具函数,直接采用mobx的inject引用是一样的,全局store如何使用就不赘述了,网上资料很多。
const Pages: FC = () => { const [viewer, setViewer] = useState<null | Cesium.
Viewer>(null) const { tiles: { tileSetList, addTileSet } } = useStores() //
const viewerRef = useRef<null | Cesium.Viewer>(null); useEffect(() => { const
view= initViewer(); initTile(view) setViewer(view); const MP = new MousePosition
(view); }, []) const initTile = (viewer:Cesium.Viewer) => { const tileBuilding =
viewer!.scene.primitives.add( new Cesium.Cesium3DTileset({ // 3d titles url:
'../mock/tileset.json', }) ) tileBuilding.readyPromise .then(function (
tileBuilding: Cesium.Cesium3DTileset) { addTileSet('Building', tileBuilding) })
.catch(function (error: any) { console.log(error); }); const tileBIM = viewer!.
scene.primitives.add( new Cesium.Cesium3DTileset({ // 3d titles url: Cesium.
IonResource.fromAssetId(8564), }) ) tileBIM.readyPromise .then(function (tileBIM
: Cesium.Cesium3DTileset) { addTileSet('BIM', tileBIM) }) .catch(function (error
: any) { console.log(error); }); } const add3DTile = (tileObj: TileProp) => { if
(!viewer) return message.error('图层未加载'); viewer.zoomTo( tileSetList[tileObj.
title], new Cesium.HeadingPitchRange( // heading pitch roll 0.5, -0.2,
tileSetList[tileObj.title].boundingSphere.radius * 4.0 ) ); return } return ( <
div className={styles.cesiumPage}> <MapHeader viewer={viewer} onRadioChange={
add3DTile} /> <div className={styles.cesiumPageContainer}> <LayerEdit viewer={
viewer} /> <div className={styles.baseMapWrapper}> <Titles /> </div> </div> </
div> ); } export default Pages
同样的,在左侧组件中通过Antd的Tree勾选节点可以很方便控制显隐: tileSetList[key].show = info.checked。
// 引入全局Store,只用到了tileSetList const { tiles: { tileSetList, addTileSet } } =
useStores() ··· ··· // 省略无用代码 // Tree选中节点的触发的事件 const onCheck = (checkedKeys:any
, info:CheckInfo) => { const layers = getLayersById(info) console.log('onCheck',
checkedKeys, info, layers); // @ts-ignore if (info.node.type === 'geojson' &&
viewer){ viewer.dataSources.getByName(info.node.title as string)[0].show = info.
checked; } // @ts-ignore if (info.node.type === '3dtiles' && viewer){ const key
= info.node.title as string console.log('3dtiles',tileSetList,tileSetList[key])
// get方法通过索引获取数组元素,实践证明不大好用 // viewer.scene.primitives.get(info.node.key as
number).show = info.checked; tileSetList[key].show = info.checked // 设置显隐 } };
这样子就达到目的了。
模型显示:

模型隐藏:

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信