想实现自定义信息框,首先要在cesium初始化时,将默认的infoBox设置为false,因此要自己手动实现查询功能。
1. 监听点击事件,对arcgis/wms服务进行查询
具体实现代码如下:
const _self = this;
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
const ray = viewer.camera.getPickRay(movement.position);
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
if (cartesian) {
var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
if (cartographic) {
var xy = new Cesium.Cartesian2();
var alti = viewer.camera.positionCartographic.height;
var level = getLevel(alti);
if (imageryProvider.ready) {
xy = imageryProvider.tilingScheme.positionToTileXY(cartographic, level, xy);
var promise = imageryProvider.pickFeatures(xy.x, xy.y, level, cartographic.longitude, cartographic.latitude);
Cesium.when(promise, function (data) {
if (layerInfo && layerInfo.length > 0) {
//这里就得到了查询结果
_self.renderPopup(layerInfo, movement.position)
}
});
}
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
这里主要使用了pickFeatures接口,ArcGisMapServerImageryProvider和WebMapServiceImageryProvider都有这个接口。
接口需要瓦片坐标和地理坐标以及当前瓦片等级level参数。
瓦片坐标通过WebMapServiceImageryProvider对象的tilingScheme属性中的positionToTileXY接口获取;
这里需要点击处地理坐标和瓦片等级level,看来level参数很重要,查看api,竟然么有发现获取level的接口,心想level和相机高度一一对应,于是自己就逐级缩放,测试出一组参数(可能有些不准确):
原文在这里
getLevel(height) {
if (height > 48000000) {
return 0;
} else if (height > 24000000) {
return 1;
} else if (height > 12000000) {
return 2;
} else if (height > 6000000) {
return 3;
} else if (height > 3000000) {
return 4;
} else if (height > 1500000) {
return 5;
} else if (height > 750000) {
return 6;
} else if (height > 375000) {
return 7;
} else if (height > 187500) {
return 8;
} else if (height > 93750) {
return 9;
} else if (height > 46875) {
return 10;
} else if (height > 23437.5) {
return 11;
} else if (height > 11718.75) {
return 12;
} else if (height > 5859.38) {
return 13;
} else if (height > 2929.69) {
return 14;
} else if (height > 1464.84) {
return 15;
} else if (height > 732.42) {
return 16;
} else if (height > 366.21) {
return 17;
} else {
return 18;
}
},
最后就是获取查询结果,pickFeatures接口是异步的,我们使用promise获取。
2.自定义信息框,分页展示
因为arcgis服务点击查到的要素可能为多个,所以应分页展示查到的结果。
renderPopup函数主要是将查询到的结果处理成一个contentArr 数组,方便点击页码更换内容。
renderPopup = (layerInfo, position) => {
const { viewer, handler } = this.props;
let contentArr = [];
let page = '';
for (let i = 0; i < layerInfo.length; i++) {
// 处理查询到的结果
const data = layerInfo[i].data;
const content = `<div>${data.attributes.OBJNAME}</div><table><tbody>
<tr><td>FID:</th><td>${data.attributes.FID}</td></tr>
<tr><td>名称:</th><td>${data.attributes.OBJNAME}</td></tr>
<tr><td>状态:</th><td>${data.attributes.OBJSTATE}</td></tr>
<tr><td>地址:</th><td>${data.attributes.DEPTNAME1}</td></tr>
</tbody></table>`;
contentArr.push(content)
// 生成页码
if (i == 0) {
page = page + `<li style="color: #fff000; border: 1px solid #fff000;" id=${i}>${i + 1}</li>`
} else {
page = page + `<li id=${i}>${i + 1}</li>`
}
}
let pageContent = `<ul id="page">${page}</ul>`
this.infoPopuEvent(handler, position, contentArr, pageContent)
}
infoPopuEvent函数主要实现了自定义的弹窗:
infoPopuEvent = (handler, position, contentArr, pageContent) => {
const infoDiv = `<div id="trackPopUp" class="trackPopUp">
<div id="trackPopUpContent" class="leaflet-popup" style="top:5px;left:0;">
<a class="leaflet-popup-close-button" href="#">×</a>
<div class="leaflet-popup-content-wrapper">
<div id="trackPopUpLink" class="leaflet-popup-content">
</div>
<div class="leaf-popup-page">${pageContent}</div>
</div>
</div>
</div>`;
if ($("#trackPopUp").length > 0) {
$('#trackPopUp').remove();
}
$('#cesiumContainer').append(infoDiv);
$('#trackPopUp').show();
//页码点击事件
$('#page li').click(e => {
const index = parseInt(e.currentTarget.id)
const liChild = $('#page').children();
$(liChild[index]).css({ "color": "#fff000", "border": "1px solid #fff000" })
$(liChild[index]).siblings().css({ "color": "#fff", "border": "1px solid #fff" })
$('#trackPopUpLink').empty();
$('#trackPopUpLink').append(contentArr[index]);
})
var obj = { position: position, content: contentArr[0] };
infoWindow(obj);
function infoWindow(obj) {
$('.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);
$('.leaflet-popup-close-button').click(function () {
$('#trackPopUp').hide();
$('#trackPopUpLink').empty();
$('.cesium-selection-wrapper').hide();
return false;
});
//绑定地图移动
handler.setInputAction(function (movement) {
$('#trackPopUp').hide();
}, Cesium.ScreenSpaceEventType.LEFT_UP);
//绑定地图缩放
handler.setInputAction(function (movement) {
$('#trackPopUp').hide();
}, Cesium.ScreenSpaceEventType.WHEEL);
//绑定滚轮点击事件
handler.setInputAction(function (movement) {
$('#trackPopUp').hide();
}, Cesium.ScreenSpaceEventType.MIDDLE_DOWN);
},
css代码:
/*--------------------------气泡弹窗Start---------------------------*/
.trackPopUp {
display: none;
color: rgb(255, 255, 255);
}
.leaflet-popup {
position: absolute;
z-index: 100;
}
.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
font: 25px/25px Tahoma, Verdana, sans-serif;
color: rgb(255, 255, 255);
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-popup-content-wrapper {
max-height: 500px;
overflow-y: auto;
min-height: 180px;
width: 300px;
padding: 1px;
text-align: left;
border-radius: 5px;
background-color: #002445;
}
.leaflet-popup-content {
margin: 5px 20px;
line-height: 1.4;
}
.leaf-popup-page {
position: absolute;
right: 0;
bottom: 0;
}
.leaf-popup-page ul li {
margin: 3px;
width: 20px;
height: 20px;
text-align: center;
border: 1px solid #fff;
text-decoration: none;
list-style:none;
float: left;![在这里插入图片描述](https://img-blog.csdnimg.cn/20200111162952596.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hyeTEyNDM5MTY4NDQ=,size_16,color_FFFFFF,t_70)
}
.leaf-popup-page ul li:hover {
color: #fff000;
border: 1px solid #fff000;
cursor: pointer;
}
.leaflet-popup-content div {
text-align: center;
font-size: 18px;
}
.leaflet-popup-content table {
margin-top: 15px;
}
.leaflet-popup-content table tr {
height: 25px;
}
/*--------------------------气泡弹窗END---------------------------*/
效果图如下: