概要
项目开发中经常遇到需要对专题图服务的图层进行控制,在使用 ArcGIS/GeoScene Server 的时候这点很好实现。
通过 ArcGIS/GeoScene Server 发布的 MapServer 能够很好的构建带有子分组的图层组,也能对图层设置中文别名。服务地址加上 f=pjson
访问参数能直接获取图层树 json 信息,ArcGIS /GeoScene API for JS v4.x 还提供了 MapImageLayer
类来加载并控制子图层。
GeoServer 相对 ArcGIS/GeoScene Server 来说并不能直接发布对应的专题图层,但仍能通过自身的【图层组】功能实现类似的专题图服务发布与应用。
发布图层组
GeoServer 具备发布【图层组】的能力,但不能像 ArcGIS/GeoScene Server 一样一步到位,因为 GeoServer 图层组不支持直接对内部图层进行再次分组,需要将各个分组先发布成图层组,再将分组加入目标图层组,具体可参考下述操作:
-
创建子分组的图层组
💡 为方便后续查询,需做以下设置:
- 【命名】可设置为英文图层名,【标题】可设置为中文别名
- 指定【工作区】,方便数据筛查
- 【模式】设置为
named tree
-
重复以上操作,创建所有子分组;
-
创建目标图层组,加入之前创建的图层组,作为子图层组;
-
获取图层信息
-
方式一:通过 GeoServer REST API 获取信息 ,但需要进行身份验证
GET /geoserver/rest/layergroups/{layerGroupName}.json
-
方式二:通过
GetCapabilities
获取指定工作区的 XML 能力文档,从WMS_Capabilities.Capability.Layer
中过滤出目标图层组,Name
节点对应【命名】,Title
节点对应【标题】。💡 需要注意以下几点:
- 能力文档会获取指定工作空间下的所有图层和图层组,需要根据需求进行过滤筛查
- 图层组和子图层组的【模式】都需设置为
named tree
,否则能力文档无法展示子图层信息 - 图层组不支持 WFS 操作,WFS 仅针对单个图层设计。GeoServer 的图层组主要用于将多个图层组合在一起以实现样式或渲染的共享,而不是用于跨多个图层执行数据查询。此外,每个图层可能有自己的特性和属性,这使得使用单个 WFS 查询处理图层组数据变得复杂。因此,如果需要对属于同一图层组的多个图层进行数据查询,需要对每个图层单独执行 WFS 查询。
-
服务加载与查询
ArcGIS /GeoScene API for JS v4.x
图层加载
使用 WMSLayer
加载图层组(为方便图层控制,不采用 WMTS 格式)
// 添加管线图层
const layerGroupName = 'pipeLine';
const layer = new WMSLayer({
url: 'http://yourGeoserverInstance/geoserver/{workspace}/wms',
sublayers: [{
name: layerGroupName
}],
spatialReference:{wkid:number} //! important
});
图层树信息获取
通过能力文档获取图层组图层列表信息
const url = 'http://yourGeoserverInstance/geoserver/{workspace}/wms?service=wms&version=1.3.0&request=GetCapabilities';
let groups;
axios.get(url).then(
function (response) {
// 需要借助第三方库将 xml 解析成 json
const wmsCapabilities = xmltojson(response.data);
// 需要将专题图筛选出来
groups = wmsCapabilities.WMS_Capabilities.Capability.Layer.Layer.find((layer) => layer.Name === layerGroupName).Layer;
},
function (error) {
console.error(error);
}
);
图层显隐控制
通过变更WMSLayer
的 sublayers
属性控制当前展示的图层
layer.sublayers = [
{
name: 'sublayer1'
},
{
name: 'sublayer2'
}
];
要素信息拾取
通过 WMS 的 GetFeatureInfo
拾取要素信息
view.on('click', function (event) {
// 获取可见图层
const layers = layer.sublayers
.filter(({ visible, queryable, name }) => visible && queryable && name)
.map(({ name }) => name)
.join();
const x = event.mapPoint.x;
const y = event.mapPoint.y;
// 拾取容差处理
const toleranceInMeters = 10;
const xmin = x - toleranceInMeters;
const xmax = x + toleranceInMeters;
const ymin = y - toleranceInMeters;
const ymax = y + toleranceInMeters;
const { spatialReference: { latestWkid, wkid} } = view.extent;
const bbox = `${xmin},${ymin},${xmax},${ymax}`;
const crs = `EPSG:${latestWkid ?? wkid}`;
request(layer.featureInfoUrl, {
query: {
SERVICE: "WMS",
LAYERS: layers,
QUERY_LAYERS: layers,
REQUEST: "GetFeatureInfo",
INFO_FORMAT: "application/json",
FEATURE_COUNT: 5,
BBOX: bbox,
CRS: crs,
WIDTH: view.width,
HEIGHT: view.height,
I: Math.round(event.x),
J: Math.round(event.y)
}
}).then(({data}) => { // to do something });
});
OpenLayers 3
图层加载
使用 ImageWMS
加载图层组
// 添加管线图层
const layerGroupName = 'pipeLine';
const layer = new ol.layer.Image({
source: new ol.source.ImageWMS({
ratio: 1,
url: 'http://yourGeoserverInstance/geoserver/{workspace}/wms',
params: {
'FORMAT': 'image/png',
'VERSION': '1.1.1',
"LAYERS": layerGroupName,
}
})
});
图层树信息获取
同上
图层显隐控制
通过变更ImageWMS
的 updateParams
属性来更新当前展示的图层
layer.getSource().updateParams = ({'LAYERS': 'sublayer1,sublayer2'});
要素信息拾取
通过 WMS 的 GetFeatureInfo
拾取要素信息
map.on('singleclick', function(evt) {
const view = map.getView();
const viewResolution = view.getResolution();
const source = layer.getSource();
const url = source.getGetFeatureInfoUrl(
evt.coordinate,
viewResolution,
view.getProjection(),
{
'INFO_FORMAT': 'application/json',
'FEATURE_COUNT': 5
});
request(url).then(({data}) => { // to do something });
});