最近使用Cesium結(jié)合ts和react自己手動(dòng)搭建了一個(gè)基本界面,加載3dTiles數(shù)據(jù)和geojson數(shù)據(jù),動(dòng)態(tài)控制圖層的顯隱。本來以為是非常簡(jiǎn)單的功能,但是實(shí)際操作中發(fā)現(xiàn)有一些地方值得注意。
搭建的效果就是這個(gè)樣子,經(jīng)典的頂部header+左側(cè)布局,主視窗顯示地圖:
加載geojson數(shù)據(jù)源的方法很簡(jiǎn)單,Cesium.GeoJsonDataSource.load方法會(huì)返回Promise<Cesium.GeoJsonDataSource> 類型的Promise(resolve),給其指定一個(gè)固定的標(biāo)識(shí)name。
代碼:
const shandongJson = Cesium.GeoJsonDataSource.load(
'../mock/shandong.geojson',
{
clampToGround:true
}
)
shandongJson.then((shandongJson)=>{
shandongJson.name = '山東';
viewRef.dataSources.add(shandongJson)
})
因?yàn)橛?Cesium.Viewer.dataSources.getByName() 方法,直接通過name屬性獲取對(duì)應(yīng)的geojson對(duì)象。
// 涉及業(yè)務(wù)代碼的部分就不放上了 重點(diǎn)是getByName方法
if (info.node.type === 'geojson' && viewer){
viewer.dataSources.getByName(info.node.title as string)[0].show = info.checked;
}
但是在加載3dTile數(shù)據(jù)時(shí),就沒這么方便了,當(dāng)我向Viewer中同時(shí)添加json數(shù)據(jù)源和3dTile數(shù)據(jù)時(shí),通過打印其存儲(chǔ)位置,發(fā)現(xiàn)是這樣的:
在Cesium官網(wǎng)上查閱沒有一個(gè)可以直接獲取Cesium3DTileset對(duì)象實(shí)例的方法,通過index獲取獲取實(shí)例顯然不太可行,沒辦法,只能想一個(gè)其它的方法用來存儲(chǔ)Cesium3DTileset對(duì)象。于是使用Mobx建立全局store,思路如下,Redux和Vuex也是同理,只是語法不同。
import { action, extendObservable, runInAction } from "mobx";
import * as Cesium from 'cesium'
interface tileSetListProp {
[key: string]: Cesium.Cesium3DTileset
}
interface OBSERVABLE_PROP {
tileSetList: tileSetListProp
}
// 可觀察屬性
const OBSERVABLE: OBSERVABLE_PROP = {
tileSetList: {},
};
// 建立下面的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)
// {
// 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();
頁面加載時(shí):引入全局變量,在數(shù)據(jù)加載時(shí)把它存進(jìn)去:addTileSet(‘Building’, tileBuilding), useStores是一個(gè)工具函數(shù),直接采用mobx的inject引用是一樣的,全局store如何使用就不贅述了,網(wǎng)上資料很多。
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
同樣的,在左側(cè)組件中通過Antd的Tree勾選節(jié)點(diǎn)可以很方便控制顯隱: tileSetList[key].show = info.checked。文章來源:http://www.zghlxwxcb.cn/news/detail-477232.html
// 引入全局Store,只用到了tileSetList
const {
tiles: {
tileSetList,
addTileSet
}
} = useStores()
···
··· // 省略無用代碼
// Tree選中節(jié)點(diǎn)的觸發(fā)的事件
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方法通過索引獲取數(shù)組元素,實(shí)踐證明不大好用
// viewer.scene.primitives.get(info.node.key as number).show = info.checked;
tileSetList[key].show = info.checked // 設(shè)置顯隱
}
};
這樣子就達(dá)到目的了。
模型顯示:
模型隱藏:文章來源地址http://www.zghlxwxcb.cn/news/detail-477232.html
到了這里,關(guān)于Cesium之3DTileset實(shí)例管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!