cesium 3dtiles模型单体化点击高亮效果
前言
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 '; viewer.selectedEntity = selectedEntity; selectedEntity.description = '
BIN | " + pickedFeature.getProperty("BIN") + " |
---|---|
DOITT ID | " + pickedFeature.getProperty("DOITT_ID") + " |
SOURCE ID | " + pickedFeature.getProperty("SOURCE_ID") + " |
BIN | " + pickedFeature.getProperty("BIN") + " |
---|---|
DOITT ID | " + pickedFeature.getProperty("DOITT_ID") + " |
SOURCE ID | " + pickedFeature.getProperty("SOURCE_ID") + " |
Longitude | " + pickedFeature.getProperty("longitude") + " |
Latitude | " + pickedFeature.getProperty("latitude") + " |
Height | " + pickedFeature.getProperty("height") + " |
Terrain Height (Ellipsoid) | " + pickedFeature.getProperty("TerrainHeight") + " |
其他小专栏例子: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 += ``; } } var content = ` ${name} ${value}
更多精彩文章,见下面的cesium小专栏:
GIS之家/Cesium专题 - 小专栏