在项目开发中使用supermap webgl进行三维地球开发,遇到了点击三维模型,展示三维模型信息框的问题。
效果需求:鼠标点击三维模型,弹出三维模型对应的信息数据,以cesium中的infobox的形式进行展示;
需求开发流程:
- 监听三维模型鼠标点击事件
cesium中通过Cesium.ScreenSpaceEventHandler进行三维模型点击事件的监听,代码如下:
modelClickEvent(viewer) {
let self = this;
//数据服务地址
let url = 'http://localhost:8090/iserver/services/data-test/rest/data'
//鼠标左键单击监听事件
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
//获取三维模型所对应的图层
let model3DLayer = viewer.scene.layers.find('mylayer');
// 数据源及数据集名称
let params = {datasource:'datasourcename',dataset:'datasetname'};
handler.setInputAction(function(movement) {
let pick = viewer.scene.pick(movement.position);
if (model3DLayer) {
// 获取三维模型的SMID
let SMID = model3DLayer.getSelection().toString();
if (SMID > 0) {
// 通过SMID进行数据服务查询 doSqlQuery是执行超图的sql查询函数,在下一步中将给出代码
self.doSqlQuery(`SMID=${SMID}`,params,url);
} else {
// alert("未获取到模型的SMID信息!");
return
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
},
- 执行超图的查询服务
在第一步的三维模型点击监听事件中,我们已经获取到了鼠标点击三维模型所对应的SMID,接着我们根据这个SMID进行数据服务查询,获取该SMID所对应的模型信息数据
代码如下:
/**------------超图服务查询-----------------*/
// 查询服务返回结果的回调函数
function onQueryComplete(queryEventArgs) {
let selectedFeatures = queryEventArgs.originResult.features;
let item = createObjByFeature(selectedFeatures[0].fieldNames,selectedFeatures[0].fieldValues);
let desp = createDescriptionHtml(item);
let degrees = [selectedFeatures[0].geometry.position.x,selectedFeatures[0].geometry.position.y,selectedFeatures[0].geometry.position.z];
let ecfPosition = Cesium.Cartesian3.fromDegreesArrayHeights(degrees);
qlEntity.name = item["姓名"];
qlEntity.description = desp;
qlEntity.position = new Cesium.ConstantPositionProperty(ecfPosition);
// 触发viewer.selectedEntity,viewer.ontick会监听entity的变化,进而显示更新后entity的信息数据
viewer.selectedEntity = qlEntity;
}
// 通过超图服务sql查询获取的feature数据,组装成一个完成的对象object
function createObjByFeature(fieldNames,fieldValues){
let obj = {};
for(let i = 0; i < fieldNames.length; i++){
// 构造对象
obj[fieldNames[i]] = fieldValues[i];
}
return obj;
}
// 查询失败的回调函数
function processFailed(queryEventArgs) {
alert('查询失败!');
}
// 执行查询操作
const doSqlQuery = function (SQL,params,url) {
var getFeatureParam, getFeatureBySQLService, getFeatureBySQLParams;
// 设置要素sql筛选条件
getFeatureParam = new SuperMap.REST.FilterParameter({
attributeFilter: SQL
});
getFeatureBySQLParams = new SuperMap.REST.GetFeaturesBySQLParameters({
queryParameter: getFeatureParam,
toIndex: -1,
datasetNames: [`${params.datasource}:${params.dataset}`] //数据源和数据集名称
});
getFeatureBySQLService = new SuperMap.REST.GetFeaturesBySQLService(url, {
eventListeners: {
"processCompleted": onQueryComplete,
"processFailed": processFailed
}
});
getFeatureBySQLService.processAsync(getFeatureBySQLParams);
}
3.将获取到的selectedFeatures 数据,进行cesium的infobox信息框展示
在第二步中,我们获取到了selectedFeatures 数据,即通过SMID查询到了数据信息。最后一步,我们需要把获取到的selectedFeatures 进行处理,最终将其信息展示出来。
第二步的onQueryComplete函数中,let item = createObjByFeature(selectedFeatures[0].fieldNames,selectedFeatures[0].fieldValues); 是把获取到selectedFeatures数据进行构造,返回一个对象数据(类似结构 ==>{id:‘1’,name:‘test’})
**let desp = createDescriptionHtml(item);**该步骤是将构造出来的item进行infobox描述,即最终展示的信息框;
以上两个函数的代码如下:
// 模拟infoxbox,构建信息框的html展示数据
const createDescriptionHtml = function (item) {
let contentHtml = '<table class="cesium-infoBox-defaultTable"><tbody>';
for (let pro in item) {
if (pro == "positions") continue;
contentHtml += '<tr><th>' + `${pro}` + '</th>' + '<td>' + `${item[pro]}` + '</td>' + '</tr>'
}
contentHtml += '</tbody></table>'
return contentHtml
};
最终点击三维模型的显示效果如下:
成功!