在剛開始的入門篇中婿禽,我們講過 Cesium 小組件的顯隱究反,感興趣的小伙伴可以查看我前面寫過的文章 Cesium初始化界面介紹及相關(guān)小組件顯隱 石咬。那問題來了,這些組件除了能控制顯隱吹截,是否能在不修改源碼的基礎(chǔ)上對(duì)其進(jìn)行擴(kuò)展重寫呢续挟?答案是當(dāng)然可以坪哄!但并不是所有的組件都能重寫帝际,本節(jié)主要講解在不修改源碼的基礎(chǔ)上,如何對(duì)以下三個(gè)常用的控件進(jìn)行修改涮拗,以達(dá)到快速實(shí)現(xiàn)實(shí)際中業(yè)務(wù)需求的功能乾戏。當(dāng)然,如果您對(duì) Cesium 源碼研究的比較深入三热,也可以通過修改源碼的方式實(shí)現(xiàn)鼓择。
homeButton組件
homeButton 功能在實(shí)際的應(yīng)用場(chǎng)景中很常見而且功能也很實(shí)用,該組件的主要功能是返回到系統(tǒng)初始化時(shí)的位置就漾。默認(rèn)是整個(gè)球的位置呐能,如下圖:
但是在實(shí)際的業(yè)務(wù)場(chǎng)景中,一般初始化范圍都是某一個(gè)城市或園區(qū)的位置抑堡,如果使用 Cesium 自帶的 homeButton 組件摆出,就需要對(duì)其進(jìn)行修改,使我們?cè)邳c(diǎn)擊homeButton時(shí)首妖,相機(jī)不是定位到Cesium自帶的默認(rèn)位置偎漫,而是定位到我們想要的位置。我們?cè)撊绾涡薷哪兀?/p>
1)修改相機(jī)的默認(rèn)矩形范圍
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(
110.15,
34.54,
110.25,
34.56
); //Rectangle(west, south, east, north)
2)在 homeButton 的 viewModel 中添加監(jiān)聽事件
if (viewer.homeButton) {
viewer.homeButton.viewModel.command.beforeExecute.addEventListener(
function (e) {
e.cancel = true;
//你要飛的位置
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(117.16, 32.71, 15000.0),
});
}
);
}
Geocoder組件
Geocoder 是地理編碼的意思有缆,我們常用的 POI 搜索就是就是 Geocoder 的功勞象踊。通過查看 Cesium 源碼(Source/Widgets/Geocoder/GeocoderViewModel.js 第73行),我們發(fā)現(xiàn)Cesium 默認(rèn)采用的是 Bing 地圖服務(wù)來實(shí)現(xiàn)地理編碼的功能棚壁,并且是通過 geocode 方法實(shí)現(xiàn)的杯矩。那么我們就可以通過覆寫 geocoder 方法的方式來實(shí)現(xiàn)自定義的地理編碼服務(wù),下面我們重寫geocode方法袖外,將 Cesium 默認(rèn)的 Bing 地圖服務(wù)改為OSM地圖服務(wù)史隆。
function OpenStreetMapNominatimGeocoder() {}
OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) {
var url = "https://nominatim.openstreetmap.org/search";
var resource = new Cesium.Resource({
url: url,
queryParameters: {
format: "json",
q: input,
},
});
return resource.fetchJson().then(function (results) {
var bboxDegrees;
return results.map(function (resultObject) {
bboxDegrees = resultObject.boundingbox;
return {
displayName: resultObject.display_name,
destination: Cesium.Rectangle.fromDegrees(
bboxDegrees[2],
bboxDegrees[0],
bboxDegrees[3],
bboxDegrees[1]
),
};
});
});
};
var viewer = new Cesium.Viewer("cesiumContainer", {
geocoder: new OpenStreetMapNominatimGeocoder(),
});
BaseLayerPicker組件
Cesium為我們提供了默認(rèn)的底圖、地形圖的選擇面板在刺,通過修改baseLayerPicker的屬性ture或false來控制顯隱逆害,通過選擇面板中的底圖或地形圖來實(shí)現(xiàn)對(duì)應(yīng)圖層的切換與顯示。Cesum 提供的默認(rèn)選擇面板如下圖所:
這些圖層都是在線的資源蚣驼,如果是離線環(huán)境,或者是只顯示客戶提供的幾個(gè)圖層數(shù)據(jù)相艇,我們?cè)撊绾螌?shí)現(xiàn)呢颖杏。要實(shí)現(xiàn)這個(gè)功能,首先坛芽,我們看一下 BaseLayerPicker 的主要邏輯關(guān)系圖留储,如下圖翼抠。
從上圖我們可以看出,對(duì)于開發(fā)者而言获讳,要實(shí)現(xiàn)不同的ImageryProvider阴颖,只需要提供不同的ProviderViewModel,比如BingMap丐膝、OSM量愧、ArcGIS、GoogleMaps的帅矗,這樣在BaseLayerPicker的UI中偎肃,就會(huì)有多個(gè)Provider供用戶選擇,而交互則由BaseLayerPickerViewModel類負(fù)責(zé)浑此,用戶并不需要關(guān)心內(nèi)部的實(shí)現(xiàn)累颂,BaseLayerPickerViewModel類已經(jīng)幫我們都實(shí)現(xiàn)了。下面我們利用 BaseLayerPicker 的邏輯關(guān)系凛俱,實(shí)現(xiàn)自定義的 ImageryProvider(高德矢量圖)和 TerrainPovider(ArcGIS地形)紊馏,并將其顯示在選擇器面板中。下面為核心代碼和結(jié)果截圖蒲犬。
// 自定義影像圖層
var imageProviderVMs = [];
let gaodeImageProvider = new Cesium.UrlTemplateImageryProvider({
url:
"http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
subdomains: ["1", "2", "3", "4"],
});
var gaodeVM = new Cesium.ProviderViewModel({
name: "高德矢量",
iconUrl: Cesium.buildModuleUrl(
"Widgets/Images/ImageryProviders/openStreetMap.png"
),
tooltip: "高德矢量 地圖服務(wù)",
creationFunction: function () {
return gaodeImageProvider;
},
});
imageProviderVMs.push(gaodeVM);
viewer.baseLayerPicker.viewModel.imageryProviderViewModels = imageProviderVMs;
// 自定義地形圖層
var terrainProviderVMs = [];
var terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({
url:
"https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
token:
"KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..",
});
var arcgisVM = new Cesium.ProviderViewModel({
name: "ArcGIS地形",
iconUrl: Cesium.buildModuleUrl(
"Widgets/Images/TerrainProviders/Ellipsoid.png"
),
tooltip: "ArcGIS地形服務(wù)",
creationFunction: function () {
return terrainProvider;
},
});
terrainProviderVMs.push(arcgisVM);
viewer.baseLayerPicker.viewModel.terrainProviderViewModels = terrainProviderVMs;
獲取完整代碼朱监,可查看本人 GitHub 地址https://github.com/ls870061011/cesium_training/tree/main/examples 中的3_1部分。