Cesium+geosever实现查询mapsever数据服务
记录一下之前项目实现的过程,初学者一名还有很多不足,请各位大神多多指点。
项目中参考了许多大佬的博客,信息框实现参考了:https://blog.youkuaiyun.com/hry1243916844/article/details/103937650
信息框和选择器的理解主要学习了:
https://www.cnblogs.com/fuckgiser/p/5702544.html
arcgis for JavaScript主要参考了:
https://blog.youkuaiyun.com/idomyway/article/details/84944607
项目实现
项目主要为了实现区域泵房数据的查询和通过列表的形式进行展示,点击列表内容能定位到相应的数据。
- 查询功能
通过cesium主要通过ArcGisMapServerImageryProvider接口实现叠加mapserver服务,信息框参考https://blog.youkuaiyun.com/hry1243916844/article/details/103937650实现,其中为了实现消息框能够跟随屏幕的效果,需要监听移动事件,这通过cesium中viewer.scene.postRender.addEventListener
实现,为此需要在点击时的坐标数据(x,y,z):
Cesium.when(promise, function(layerInfo) {
//查询结果展示
if (layerInfo && layerInfo.length > 0) {
let ifcartesian = viewer.camera.pickEllipsoid(movement.position, ellipsoid);
let ball = Cesium.Ellipsoid.WGS84.cartesianToCartographic(ifcartesian);
let info_H = scene.globe.getHeight(ball);
let infoposition = Cesium.Cartesian3.fromDegrees(layerInfo[0].data.geometry.x, layerInfo[0].data.geometry.y, info_H);//位置坐标信息
_self.renderPopup(layerInfo, movement.position, infoposition);
}
});
将该数据传递至infoWindow
函数中,因为cesium加载mapserver数据时坐标系是wgs84,跟随屏幕效果需要屏幕坐标系,这通过cesium中wgs84ToWindowCoordinates
实现:
var removeHandler = viewer.scene.postRender.addEventListener(function() {
var changedC = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, obj.infoposition);
// 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;
}
}
});
- list展示与定位
当时在实现该功能是通过arcgis for JavaScript实现的,但比较麻烦,通过cesium的方法还没实现,之后再研究下。
展示通过arcgis for JavaScript将数据存储下来,之后通过selectMenuBase插件进行展示,本项目中存储在geoserver中的数据是使用的国测2000坐标系,所以在获取数据后需要转换为wgs84坐标系,这里是通过proj4.js实现坐标系转换,使用proj4.js需要根据投影坐标系的不同进行配置,具体可参考https://epsg.io/:
var results;
var i;
var selectMenuData = [];
//查询mapserver内容,并动态添加选择框
require([
"esri/layers/ArcGISDynamicMapServiceLayer",
"esri/tasks/QueryTask",
"esri/tasks/query",
], function(
ArcGISDynamicMapServiceLayer,
QueryTask,
Query
) {
var query = new Query();
query.outFields = ["*"];
query.where = "1=1";
query.returnGeometry = true;
//实例化查询对象
var queryTask = new QueryTask("geoserver地址“);
//进行查询
queryTask.execute(query, showFindResult);
});
function showFindResult(result) {
results = result;
if (result.features.length) {
for (let j = 0; j < result.features.length; j++) {
selectMenuData[j] = {
id: j,
name: result.features[j].attributes.Name
};
}
};
}
$(function() {
$('#selectMenuBase').click(function() {
$(this).selectMenu({
showField: 'name',
keyField: 'id',
search: true,
title: false, //关闭标题栏
listSize: 20, //设置显示的菜单项目个数(菜单高度)
initSelected: 1,
data: selectMenuData,
eSelect: function(pumpdata) {
getlocal(pumpdata[0].id);
}
});
});
});
//定义4545坐标系(CGCS2000,高斯克里格 3度 CM 108E带)proj4.defs("EPSG:4545", "+proj=tmerc +lat_0=0 +lon_0=108 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
var fromProjection = "+proj=tmerc +lat_0=0 +lon_0=108 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";
//定义4326坐标系(WGS84)
var toProjection = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";
//读取对应内容坐标
function getlocal(i) {
let point = [];
point[i] = [results.features[i].geometry.x, results.features[i].geometry.y];
transformCoordinates(point[i]);
};
//利用proj4.js进行投影坐标变换,将CGCS2000,高斯克里格 3度 CM 108E带投影坐标系转换到WGS84坐标系下,并进行定位。
function transformCoordinates(point) {
//坐标转换
let transformPoint = [];
transformPoint = proj4(fromProjection, toProjection, point);
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(transformPoint[0], transformPoint[1], 1000),
});
};