前言
cesium 官網的api文檔介紹地址cesium官網api,里面詳細的介紹 cesium 各個類的介紹,還有就是在線例子:cesium 官網在線例子,這個也是學習 cesium 的好素材。
cesium官網在線例子
https://sandcastle.cesium.com/?src=3D+Tiles+Feature+Picking.html
大概思路如下:
- 加載3dtiles模型
var tileset = new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(75343), }); viewer.scene.primitives.add(tileset);
- 創建html元素,鼠標移動以及點擊模型高亮作用
// HTML overlay for showing feature name on mouseover var nameOverlay = document.createElement("div"); viewer.container.appendChild(nameOverlay); nameOverlay.className = "backdrop"; nameOverlay.style.display = "none"; nameOverlay.style.position = "absolute"; nameOverlay.style.bottom = "0"; nameOverlay.style.left = "0"; nameOverlay.style["pointer-events"] = "none"; nameOverlay.style.padding = "4px"; nameOverlay.style.backgroundColor = "black";
- 設置選中要素的樣式以及創建選中模型
// Information about the currently selected feature var selected = { feature: undefined, originalColor: new Cesium.Color(), }; // An entity object which will hold info about the currently selected feature for infobox display var selectedEntity = new Cesium.Entity();
- 鼠標響應事件交互
// 獲取默認的左鍵單擊處理程序,用於在左鍵單擊時未拾取要素 var clickHandler = viewer.screenSpaceEventHandler.getInputAction( Cesium.ScreenSpaceEventType.LEFT_CLICK ); // 如果支持剪影,則鼠標上方的剪影功能為藍色,鼠標單擊的剪影功能為綠色 // 如果不支持輪廓,請將特征顏色更改為鼠標懸停時為黃色,單擊鼠標時為綠色 if ( Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene) ) { // 支持輪廓 var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage(); silhouetteBlue.uniforms.color = Cesium.Color.BLUE;//藍色 silhouetteBlue.uniforms.length = 0.01; silhouetteBlue.selected = []; var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage(); silhouetteGreen.uniforms.color = Cesium.Color.LIME; silhouetteGreen.uniforms.length = 0.01; silhouetteGreen.selected = []; viewer.scene.postProcessStages.add( Cesium.PostProcessStageLibrary.createSilhouetteStage([ silhouetteBlue, silhouetteGreen, ]) ); // 在懸停時勾勒出藍色的輪廓 viewer.screenSpaceEventHandler.setInputAction(function onMouseMove( movement ) { // 如果先前高亮顯示了某個要素,請撤消該高亮顯示 silhouetteBlue.selected = []; //點擊新要素 var pickedFeature = viewer.scene.pick(movement.endPosition); if (!Cesium.defined(pickedFeature)) { nameOverlay.style.display = "none"; return; } //要素被點擊,顯示它的覆蓋內容 nameOverlay.style.display = "block"; nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + "px"; nameOverlay.style.left = movement.endPosition.x + "px"; var name = pickedFeature.getProperty("BIN"); nameOverlay.textContent = name; // 突出顯示尚未選定的功能 if (pickedFeature !== selected.feature) { silhouetteBlue.selected = [pickedFeature]; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 在信息框中顯示選定內容和元數據 viewer.screenSpaceEventHandler.setInputAction(function onLeftClick( movement ) { // 如果先前選擇了某個特征,請撤消高亮顯示 silhouetteGreen.selected = []; // 點擊新要素 var pickedFeature = viewer.scene.pick(movement.position); if (!Cesium.defined(pickedFeature)) { clickHandler(movement); return; } // Select the feature if it's not already selected if (silhouetteGreen.selected[0] === pickedFeature) { return; } // 保存選定要素的原始顏色 var highlightedFeature = silhouetteBlue.selected[0]; if (pickedFeature === highlightedFeature) { silhouetteBlue.selected = []; } // 高亮新選擇要素 silhouetteGreen.selected = [pickedFeature]; // 設置要素信息框描述 var featureName = pickedFeature.getProperty("name"); selectedEntity.name = featureName; selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>'; viewer.selectedEntity = selectedEntity; selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' + "<tr><th>BIN</th><td>" + pickedFeature.getProperty("BIN") + "</td></tr>" + "<tr><th>DOITT ID</th><td>" + pickedFeature.getProperty("DOITT_ID") + "</td></tr>" + "<tr><th>SOURCE ID</th><td>" + pickedFeature.getProperty("SOURCE_ID") + "</td></tr>" + "</tbody></table>"; }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } else { // 不支持輪廓。相反,更改特征顏色 // 有關當前突出顯示的功能的信息 var highlighted = { feature: undefined, originalColor: new Cesium.Color(), }; // 鼠標移動顯示黃色 viewer.screenSpaceEventHandler.setInputAction(function onMouseMove( movement ) { // 如果先前高亮顯示了某個要素,請撤消該高亮顯示 if (Cesium.defined(highlighted.feature)) { highlighted.feature.color = highlighted.originalColor; highlighted.feature = undefined; } // 點擊新要素 var pickedFeature = viewer.scene.pick(movement.endPosition); if (!Cesium.defined(pickedFeature)) { nameOverlay.style.display = "none"; return; } // 要素被點擊,顯示它的覆蓋內容 nameOverlay.style.display = "block"; nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + "px"; nameOverlay.style.left = movement.endPosition.x + "px"; var name = pickedFeature.getProperty("name"); if (!Cesium.defined(name)) { name = pickedFeature.getProperty("id"); } nameOverlay.textContent = name; // Highlight the feature if it's not already selected. if (pickedFeature !== selected.feature) { highlighted.feature = pickedFeature; Cesium.Color.clone( pickedFeature.color, highlighted.originalColor ); pickedFeature.color = Cesium.Color.YELLOW; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //為所選內容上色並在信息框中顯示元數據 viewer.screenSpaceEventHandler.setInputAction(function onLeftClick( movement ) { // 如果先前選擇了某個特征,請撤消高亮顯示 if (Cesium.defined(selected.feature)) { selected.feature.color = selected.originalColor; selected.feature = undefined; } // 點擊新要素 var pickedFeature = viewer.scene.pick(movement.position); if (!Cesium.defined(pickedFeature)) { clickHandler(movement); return; } // Select the feature if it's not already selected if (selected.feature === pickedFeature) { return; } selected.feature = pickedFeature; // Save the selected feature's original color if (pickedFeature === highlighted.feature) { Cesium.Color.clone( highlighted.originalColor, selected.originalColor ); highlighted.feature = undefined; } else { Cesium.Color.clone(pickedFeature.color, selected.originalColor); } // Highlight newly selected feature pickedFeature.color = Cesium.Color.LIME; // Set feature infobox description var featureName = pickedFeature.getProperty("name"); selectedEntity.name = featureName; selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>'; viewer.selectedEntity = selectedEntity; selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' + "<tr><th>BIN</th><td>" + pickedFeature.getProperty("BIN") + "</td></tr>" + "<tr><th>DOITT ID</th><td>" + pickedFeature.getProperty("DOITT_ID") + "</td></tr>" + "<tr><th>SOURCE ID</th><td>" + pickedFeature.getProperty("SOURCE_ID") + "</td></tr>" + "<tr><th>Longitude</th><td>" + pickedFeature.getProperty("longitude") + "</td></tr>" + "<tr><th>Latitude</th><td>" + pickedFeature.getProperty("latitude") + "</td></tr>" + "<tr><th>Height</th><td>" + pickedFeature.getProperty("height") + "</td></tr>" + "<tr><th>Terrain Height (Ellipsoid)</th><td>" + pickedFeature.getProperty("TerrainHeight") + "</td></tr>" + "</tbody></table>"; }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
其他小專欄例子:3dtiles單體化
https://xiaozhuanlan.com/topic/3241096587
具體看上述鏈接文章,里面有詳細的介紹
本篇文章效果例子:結合geoserver實現3dtiles傾斜模型單體化點擊高亮
實現思路如下:鼠標點擊傾斜模型,獲取對應的點擊坐標點;然后根據pick獲取到的坐標點,結合geoserver發布的wfs服務,進行空間查詢,匹配對應的geojson數據;最后根據獲取到的geojson數據源來繪制顯示高亮效果,並且彈出對應氣泡窗口。
效果圖:
- 監聽鼠標點擊事件:
this.handler.setInputAction(function (evt) { //單機開始繪制 var picks = viewer.scene.drillPick(evt.position); viewer.scene.render(); var cartesian; var isOn3dtiles = false; for (var i = 0; i < picks.length; i++) { if ((picks[i] && picks[i].primitive) || picks[i] instanceof Cesium.Cesium3DTileFeature) { //模型上拾取 isOn3dtiles = true; } } if (isOn3dtiles) { cartesian = viewer.scene.pickPosition(evt.position); var lnglat = cUtil.cartesianToLnglat(cartesian);//坐標轉換 that.queryWFSData([lnglat]); } else { console.warn("請到模型上拾取!"); return; } }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
- geoserver空間查詢,具體的wfs服務空間查詢參數那些可以參照這篇文章,cesium結合geoserver實現地圖空間查詢(附源碼下載):
queryWFSData: function (lnglats) { if (!lnglats || lnglats.length < 1) return; var that = this; queryWFSData({ typeName: typeName, propertyName: propertyName, url: mapUrl, queryData: { type: '1', coors: lnglats }, success: function (data) { if (!data.features || data.features.length == 0) { console.warn("未查詢到相關數據!"); return; } that.loadGeojson(data);//查詢結果高亮繪制顯示 } }) }
- 高亮繪制顯示:
loadGeojson: function (data) { if (!data) return; var that = this; Cesium.GeoJsonDataSource.load(data, { stroke: Cesium.Color.HOTPINK, fill: Cesium.Color.YELLOW.withAlpha(.8), clampToGround: true, strokeWidth: 3 }).then(function (dataSource) { that.quyerDataSourceArr.push(dataSource); viewer.dataSources.add(dataSource); var entities = dataSource.entities.values; that.bindPopup(entities); viewer.flyTo(entities, { offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90.0), 100) }); }); }
- 氣泡窗口顯示:
bindPopup: function (entities) { if (!entities || entities.length < 1) return; var that = this; entities.forEach(function (ent) { ent.attr = "loadgeojson"; var properties = ent._properties; var contentStr = ""; for (var i in properties) { var name = ppObj[i]; var value = properties[i]._value; if (name && value) { contentStr += ` <tr> <td>${name}</td> <td>${value}</td> </tr> `; } } var content = ` <table style='width:200px;'> ${contentStr} </table> `; //綁定彈窗 var hierarchy = ent.polygon.hierarchy._value.positions; var center = cUtil.getCenterByPositions(hierarchy); var lnglat = cUtil.cartesianToLnglat(center); var tileH = viewer.scene.sampleHeight(Cesium.Cartographic.fromDegrees(lnglat[0], lnglat[1])); var popupCartesian = Cesium.Cartesian3.fromDegrees(lnglat[0], lnglat[1], tileH); var popup = new MovePrompt(viewer, { type: 2, content: content, popupCartesian: popupCartesian, offset: { y: -30 } }) that.popupArr.push(popup); ent.popup = popup; }); }
更多精彩文章,見下面的cesium小專欄: