cesium 3dtiles模型單體化點擊高亮效果

前言

cesium 官網的api文檔介紹地址cesium官網api,裏面詳細的介紹 cesium 各個類的介紹,還有就是在線例子:cesium 官網在線例子,這個也是學習 cesium 的好素材。html

cesium官網在線例子

https://sandcastle.cesium.com/?src=3D+Tiles+Feature+Picking.htmlnode

大概思路以下:git

  • 加載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
具體看上述連接文章,裏面有詳細的介紹json

本篇文章效果例子:結合geoserver實現3dtiles傾斜模型單體化點擊高亮

實現思路以下:鼠標點擊傾斜模型,獲取對應的點擊座標點;而後根據pick獲取到的座標點,結合geoserver發佈的wfs服務,進行空間查詢,匹配對應的geojson數據;最後根據獲取到的geojson數據源來繪製顯示高亮效果,而且彈出對應氣泡窗口。canvas

效果圖:
api

  • 監聽鼠標點擊事件:
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);
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小專欄app

GIS之家/Cesium專題 - 小專欄​xiaozhuanlan.compost

相關文章
相關標籤/搜索