假设在GeoServer服务器上,我有一个需求,需加载经过样式文件渲染
过的图层,在这个图层上实现点击查询
,并将查询结果要素用几何图形
进行渲染并放到图层上,可以怎么实现呢?
思路:
1.样式文件渲染
那就是在服务端进行渲染后再加载到页面,这个用WMS服务可以实现
2.点击查询
WMS也能够实现点击查询
WMS输出格式 可以知道输出的格式有限,在开发者工具上查看点击图层时发送的请求,可以发现request为getFeatureInfo,就是只能够获取图层的属性表信息,不能获取几何信息
换成getMap
这就有问题了,我们不能获取几何信息,那就不能创建几何图形了鸭
所以,我们可以考虑WFS,因为它有一个请求为getFeature,经过测试,可以知道getFeature不仅可以返回属性表信息,还可以返回图层要素的几何信息。
cql_filter介绍
// ArcGIS for JS的js代码 view.on("click", (event) => { let url = "http://localhost:9090/geoserver/guangdong/wfs"; let query = { SERVICE: "WFS", REQUEST: "GetFeature", VERSION: "2.0.0", TYPENAMES: "guangdong", OUTPUTFORMAT: "json", SRSNAME: "EPSG:4326", cql_filter: `INTERSECTS(the_geom,%20POINT%20(${event.mapPoint.latitude}%20${event.mapPoint.longitude}))`, }; //发送请求 get(url, query, callRes); });
因此,整体思路就是,用WMS加载渲染过后的图层(因为图层数据是在GeoServer,正常没有关闭WFS服务的话,也是能用的),用WFS服务的getFeature过滤点击查询的点,返回点击的图层要素的图层属性和几何属性,再用Graphic进行创建及渲染成几何图形,添加至图层。
所有代码
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <title>demo</title> <style> html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } </style> <link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css" /> <script src="https://js.arcgis.com/4.22/"></script> <script> require([ "esri/Map", "esri/views/SceneView", "esri/layers/WMSLayer", "esri/layers/SceneLayer", "esri/layers/GraphicsLayer", "esri/layers/WFSLayer", "esri/Graphic", ], ( Map, SceneView, WMSLayer, SceneLayer, GraphicsLayer, WFSLayer, Graphic, ) => { const map = new Map({ basemap: "topo-vector", }); const view = new SceneView({ container: "viewDiv", map: map, }); // 加载wmsLayer let wmsLayer = new WMSLayer({ url: "http://localhost:9090/geoserver/guangdong/wms", sublayers: [ { name: "guangdong", }, ], }); console.log("wmsLayer", wmsLayer); map.add(wmsLayer); view.when(() => { view.goTo(wmsLayer.fullExtent); }); // 创建一个GraphicLayer,用来绘制查询结果 var graphicsLayer = new GraphicsLayer(); map.add(graphicsLayer); view.on("click", (event) => { let url = "http://localhost:9090/geoserver/guangdong/wfs"; let query = { SERVICE: "WFS", REQUEST: "GetFeature", VERSION: "2.0.0", TYPENAMES: "guangdong", OUTPUTFORMAT: "json", SRSNAME: "EPSG:4326", cql_filter: `INTERSECTS(the_geom,%20POINT%20(${event.mapPoint.latitude}%20${event.mapPoint.longitude}))`, }; //发送请求 get(url, query, callRes); }); //回调函数 function callRes(result) { console.log("result:", result); addGraphics(result.features); } //发送请求 function get(url, query, callback) { // 如果有参数,先把参数拼接在url后面 if (query) { url += "?"; for (let key in query) { url += `${key}=${query[key]}&`; } // 去除最后多余的那一个& url = url.slice(0, -1); } let xhr = new XMLHttpRequest(); xhr.responseType = "json"; xhr.open("get", url); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { // console.log("xhr",xhr) callback(xhr.response); } } }; } //添加几何图形 function addGraphics(result) { graphicsLayer.removeAll(); result.forEach(function (item) { if (item.geometry.type === "point") { } else if (item.geometry.type === "polyline") { } else if ( item.geometry.type === "polygon" || item.geometry.type === "MultiPolygon" ) { const fillSymbol = { type: "simple-fill", color: [227, 227, 2, 0.8], outline: { color: [255, 255, 255], width: 1, }, }; var polygons = item.geometry.coordinates.map(ring => { return new Graphic({ geometry: { type: "polygon", rings: ring, }, symbol: fillSymbol, spatialReference: view.spatialReference, }); }) } graphicsLayer.addMany(polygons); view.goTo(polygons); }); } }); </script> </head> <body> <div id="viewDiv"></div> </body> </html>