cesium加载gltf模型点击以及列表点击定位弹窗

Posted giserhome

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cesium加载gltf模型点击以及列表点击定位弹窗相关的知识,希望对你有一定的参考价值。

前言

cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材。

之前有部分订阅者咨询我,cesium加载gltf模型点击弹窗以及模型列表点击定位弹窗那些交互是怎么实现的,虽说比较简单,但是总有新手是有这块需求的。所以,今天我抽空整理一下本篇素材,简单写一下。

实现效果图如下:
技术图片

大概思路如下:

  • gltf模型的模拟数据源配置,配置gltf模型路径以及气泡窗口显示内容json数据源
/*三维模型gltf配置信息*/
MapConfig.mapPosition = Cesium.Cartesian3.fromDegrees(102.468086, 37.933179,3500);
MapConfig.position = Cesium.Cartesian3.fromDegrees(102.468086, 37.933179);
MapConfig.Obj3D = {
position:MapConfig.mapPosition,
models:[
{
id:"1_db",
name : "测试3D模型1_db",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_db.gltf"
},
{
id:"1_deng",
name : "测试3D模型1_deng",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_deng.gltf"
},
{
id:"1_men",
name : "测试3D模型1_men",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_men.gltf"
},
{
id:"1_my",
name : "测试3D模型1_my",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_my.gltf"
},
{
id:"1_pao",
name : "测试3D模型1_pao",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_pao.gltf"
},
{
id:"1_w",
name : "测试3D模型1_w",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_w.gltf"
},
{
id:"1_wd",
name : "测试3D模型1_wd",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_wd.gltf"
},
{
id:"1_wl",
name : "测试3D模型1_wl",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_wl.gltf"
},
{
id:"1_wq",
name : "测试3D模型1_wq",
type:"gltf",
position : MapConfig.position,
uri :"http://localhost:8180/cesium/3DModel/test/gltf/1_wq.gltf"
}
 
]
};
/*配置三维模型gltf气泡窗口内容模拟数据源*/
MapConfig.Obj3Djson = [
{
id:"1_db",
name : "测试3D模型1_db",
address:"测试3D模型地址"
},
{
id:"1_deng",
name : "测试3D模型1_deng",
address:"测试3D模型地址"
},
{
id:"1_men",
name : "测试3D模型1_men",
address:"测试3D模型地址"
},
{
id:"1_my",
name : "测试3D模型1_my",
address:"测试3D模型地址"
},
{
id:"1_pao",
name : "测试3D模型1_pao",
address:"测试3D模型地址"
},
{
id:"1_w",
name : "测试3D模型1_w",
address:"测试3D模型地址"
},
{
id:"1_wd",
name : "测试3D模型1_wd",
address:"测试3D模型地址"
},
{
id:"1_wl",
name : "测试3D模型1_wl",
address:"测试3D模型地址"
},
{
id:"1_wq",
name : "测试3D模型1_wq",
address:"测试3D模型地址"
}
];
  • cesium加载gltf三维模型
cesium.add3DGlft(MapConfig.Obj3D);
/**
* 加载GLFT模型
* @method add3DGlft
* @param
* @return
*/
add3DGlft: function (obj) {
//加载3dModel
this.add3DEntityModels(obj.models);
},
/**
* 批量加载3D模型
* @method add3DEntityModels
* @param models 3D模型数组
* @return
*/
add3DEntityModels: function (models) {
//var heading = Cesium.Math.toRadians(45.0);
//var pitch = Cesium.Math.toRadians(15.0);
//var roll = Cesium.Math.toRadians(0.0);
//var orientation = Cesium.Transforms.headingPitchRollQuaternion(
//position, heading, pitch, roll);
if(models && models.length>0){
for(var i=0;i<models.length;i++){
var type = null;
if(models[i].type){
type = models[i].type;
}
var entity = this.cesiumViewer.entities.add({
name : models[i].name,
//id:models[i].id+Math.random().toString(36).substr(2),
id:models[i].id,
type : type,
position : models[i].position,
//orientation : orientation,
model : {
uri : models[i].uri,
//distanceDisplayCondition : new Cesium.DistanceDisplayCondition(100, 5000),//设置模型可见范围,100米到5000米
//maximumScale:12,
//incrementallyLoadTextures:false,//确定在加载模型后,是否继续加载纹理
}
});
//this.cesiumViewer.trackedEntity = entity;//建议不跟踪定位3D模型,不然锁定视角操作不灵活
}
}
},
  • html界面的gltf列表面板设计以及动态加载
<!--三维模型gltf列表-->
<div id="showListsDIV" style="display:none;position: absolute;right:80px;top:40px;background: #0101018a;width: 300px;height: 650px;z-index:99;">
<div id="showLists" style="height:99%;"></div>
</div>
/**
*加载gltf信息列表
*/
function loadGltfList(){
var data = MapConfig.Obj3Djson;
if(data && data.length>0){
var innerStr = [];
for(var i=0;i<data.length;i++){
//innerStr.push(‘<div class="left_list_li_box" id = "‘ + data[i].id + ‘" onclick="this.toLocationGltf(‘‘ + data[i].id + ‘‘)">‘);
innerStr.push(‘<div class="left_list_li_box" id = "‘ + data[i].id + ‘">‘);
innerStr.push(‘<div class="left_list_li_box_top">‘);
innerStr.push(‘<div class="left2_box2">‘);
innerStr.push(‘<img class="list_poi_marker" src="./gis/cesium/images/poiLocation.png"></img>‘);
innerStr.push(‘<div class="left_list_li1">‘);
innerStr.push(‘<p>‘);
innerStr.push(‘<a>id:‘ + data[i].id + ‘</a><br/>‘);
innerStr.push(‘<a>名称:‘ + data[i].name + ‘</a><br/>‘);
innerStr.push(‘<a>地址:‘ + data[i].address + ‘</a><br/>‘);
innerStr.push(‘</p>‘);
innerStr.push(‘</div>‘);
innerStr.push(‘</div>‘)
innerStr.push(‘</div>‘);
innerStr.push(‘</div>‘);
}
$("#showLists").html(innerStr.join(‘‘));
$(".left_list_li_box").click(function(e){
//console.log("left_list_li_box",e.currentTarget.id);
var id = e.currentTarget.id;
toLocationGltf(id);
});
//滚动条样式
$("#showLists").mCustomScrollbar({
theme: "minimal-dark",
});
}
}
loadGltfList();
  • gtlf模型别来点击弹窗函数,根据模型的id去匹配对应的模型entity,然后利用entity来进行弹窗显示相关内容展示
/**
* 根据id匹配对应的模型
* @param id gltf模型id
*/
function toLocationGltf(id){
var entity = cesium.cesiumViewer.entities.getById(id);
if (entity instanceof Cesium.Entity){
for(var i = 0;i<MapConfig.Obj3Djson.length;i++){
var data = MapConfig.Obj3Djson[i];
if(id == data.id){
var content =
"<div>"+
"<span>名称:</span><span>"+data.name+"</span></br>"+
"<span>地址:</span><span>"+data.address+"</span></br>"+
"</div>";
var cartographic = Cesium.Cartographic.fromCartesian(entity._position._value);//世界坐标转地理坐标(弧度)
//var point=[ cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180];//地理坐标(弧度)转经纬度坐标
var point=[ Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)];//地理坐标(弧度)转经纬度坐标
var popupCartesian=Cesium.Cartesian3.fromDegrees(point[0], point[1], 0);
var position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(cesium.cesiumViewer.scene, popupCartesian);
var obj = {position:position,content:content};
cesium.infoWindow(obj);
break;
}
}
}
}
  • 气泡窗口函数
/**
* 弹出气泡窗口
* @method infoWindow
* @param obj{position(必填):屏幕坐标,destination(必填):跳转目的点,content(必填):气泡窗口内容,css(可填):设置css的width,height}
* @return 返回选中的模型Entity
*/
infoWindow: function (obj) {
var picked = this.cesiumViewer.scene.pick(obj.position);
if (Cesium.defined(picked)) {
var viewer = this.cesiumViewer;
var id = Cesium.defaultValue(picked.id, picked.primitive.id);
if (id instanceof Cesium.Entity) {
// if(obj.destination){
// this.cesiumViewer.camera.flyTo({//初始化跳转某个地方
// destination : obj.destination
// });
// }
//填充内容
$(".cesium-selection-wrapper").show();
$(‘#trackPopUpLink‘).empty();
$(‘#trackPopUpLink‘).append(obj.content);
function positionPopUp (c) {
var x = c.x - ($(‘#trackPopUpContent‘).width()) / 2;
var y = c.y - ($(‘#trackPopUpContent‘).height());
$(‘#trackPopUpContent‘).css(‘transform‘, ‘translate3d(‘ + x + ‘px, ‘ + y + ‘px, 0)‘);
}
var c = new Cesium.Cartesian2(obj.position.x, obj.position.y);
$(‘#trackPopUp‘).show();
positionPopUp(c); // Initial position at the place item picked
var removeHandler = viewer.scene.postRender.addEventListener(function () {
var changedC = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, id._position._value);
// If things moved, move the popUp too
if(c && changedC && c.x && changedC.x && c.y && changedC.y){
if ((c.x !== changedC.x) || (c.y !== changedC.y)) {
positionPopUp(changedC);
c = changedC;
}
}
 
});
// PopUp close button event handler
$(‘.leaflet-popup-close-button‘).click(function() {
$(‘#trackPopUp‘).hide();
$(‘#trackPopUpLink‘).empty();
$(".cesium-selection-wrapper").hide();
removeHandler.call();
return false;
});
return id;
}
}
},
  • 点击三维模型gltf,弹窗显示
//调用接口-气泡窗口
var handler3D = new Cesium.ScreenSpaceEventHandler(cesium.cesiumViewer.scene.canvas);
handler3D.setInputAction(function(movement) {
//点击弹出气泡窗口
var pick = cesium.cesiumViewer.scene.pick(movement.position);
if(pick && pick.id && pick.id._position){//选中某模型
var cartographic = Cesium.Cartographic.fromCartesian(pick.id._position._value);//世界坐标转地理坐标(弧度)
var point=[ Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)];//地理坐标(弧度)转经纬度坐标
var destination=Cesium.Cartesian3.fromDegrees(point[0], point[1], 3000.0);
//判断是否弹出气泡窗口内容
switch (pick.id._type)
{
case "gltf":
for(var i = 0;i<MapConfig.Obj3Djson.length;i++){
var data = MapConfig.Obj3Djson[i];
if(pick.id._id == data.id){
var content =
"<div>"+
"<span>名称:</span><span>"+data.name+"</span></br>"+
"<span>地址:</span><span>"+data.address+"</span></br>"+
"</div>";
var obj = {position:movement.position,destination:destination,content:content};
cesium.infoWindow(obj);
break;
}
}
break;
}
}
else{
$(‘#trackPopUp‘).hide();
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

更多精彩文章,见下面的cesium小专栏

GIS之家/Cesium专题 - 小专栏?xiaozhuanlan.com

以上是关于cesium加载gltf模型点击以及列表点击定位弹窗的主要内容,如果未能解决你的问题,请参考以下文章

cesium加载3D—gltf模型

ThreeJS 加载gltf模型过暗问题解决

使用Blender导出多个动画的GLTF模型

surfer如何导出三维gltf文件

cesium导入3D模型(obj转gltf)

Cesium专栏-terrain地形3dtiles模型gltf模型 高度采样