一 .效果图
1.操作方式支持查询 新增 删除 修改操作 。除了查询选中地图选择操作方式即可执行。我这底图瓦片比较多加载慢。
二 代码
我用的html +js
在这个页面中,使用的是songbei_map_layer_test图层,这个图层有一个几何字段geometry有一个name名字字段,几何类型是POLYGON,坐标系在建表的时候已经建立好了,必须是4326,这样才能支持geoserver的WFS服务,不至于报错。
页面代码需要注意得 都加入注解了。修改的地方不多 基本上就是地址,工作区名字与图层名
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>openlayer与geoserver交互</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.6.1/css/ol.css" /> <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.6.1/build/ol.js"></script> <script src="jquery-1.7.2.min.js"></script> <style type="text/css"> #map, html, body { height: 100%; width: 100%; } </style> </head> <body> <form class="form-inline"> <label>操作方式 </label> <select id="interaction"> <option value="search">查看</option> <option value="insert">增加</option> <option value="modify">修改</option> <option value="delete">删除</option> </select> <label>先操作对象,再点击 </label> <input type="button" id="creategml" name="name" value="提交" /> </form> <div id="map"></div> <div id="attributetable"> <table> <thead> <tr> <th>fid</th> <th>name</th> <!-- <th>name_ch</th>--> </tr> </thead> <tbody id="attributetbody"> </tbody> </table> </div> <style type="text/css"> #map { width: 80%; height: 80%; } #attributetable { width: 100%; height: 5%; margin: 10px; } table { border-collapse: collapse; border-spacing: 0; border: 1px solid #c0c0c0; } th,td { border: 1px solid #d0d0d0; color: #404060; padding: 10px; } th { background-color: #C00000; font: bold 16px "微软雅黑"; color: #fff; } td { font: 14px "微软雅黑"; } tbody tr { background-color: #f0f0f0; } tbody tr:hover { cursor: pointer; background-color: #fafafa; } </style> <script type="text/javascript"> //geoserver地址,可变配置提出 var baseurl ='http://192.168.3.127:8180/'; // 获取坐标系 var proj4326=ol.proj.get('EPSG:4326'); // 打印坐标系的轴方向,默认的轴方向为neu,生成GML文件,经纬度会是反的 console.log("12312"+proj4326.getAxisOrientation()); // 新建坐标系,修改轴方向为enu,经度、纬度、高程 var proj = new ol.proj.Projection({ code: 'EPSG:4326', axisOrientation: 'enu', units:proj4326.getUnits(), canWrapX:true, extent:proj4326.getExtent(), global:true, worldExtent:proj4326.getWorldExtent(), }); // 覆盖原来的4326坐标系,目的是为了保证生成GML文件中经纬度不反 ol.proj.addProjection(proj); var proj4326new=ol.proj.get('EPSG:4326'); console.log(proj4326new); //视窗,openlayer默认坐标系是平面墨卡托,设定为WGS84 var view = new ol.View({ center: [126.36,45.45], zoom: 9, projection: 'EPSG:4326', }); var gr = new ol.tilegrid.TileGrid({ origin : [ -180.0,-90.0 ], resolutions : [ 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 6.866455078125E-4, 3.4332275390625E-4, 1.71661376953125E-4, 8.58306884765625E-5, 4.291534423828125E-5, 2.1457672119140625E-5, 1.0728836059570312E-5, 5.364418029785156E-6, 2.682209014892578E-6, 1.341104507446289E-6, 6.705522537231445E-7, 3.3527612686157227E-7 ] }); //曾经的腾讯底图 <!-- new ol.layer.Tile({--> <!-- source: new ol.source.XYZ({--> <!-- url: "http://rt{0-3}.map.gtimg.com/realtimerender?z={z}&x={x}&y={-y}&type=vector&style=0"--> <!-- })--> <!-- }),--> //图层,加载腾讯底图和geoserver发布的wmts var layers = [ //底图地址与样式 new ol.layer.Tile({ source : new ol.source.TileWMS({ url : 'http://192.168.3.127:8180/geoserver/songbei/wms?', params : { 'FORMAT' : 'image/png', 'VERSION' : '1.1.1', 'SRS' : 'EPSG:4326', 'tiled' : true, 'LAYERS' : 'songbei:songbei_map_layer_test', STYLES : '' }, tileGrid : gr, serverType: 'geoserver' }) }), //图层地址与样式 new ol.layer.Image({ source: new ol.source.ImageWMS({ ratio: 1, url:'http://192.168.3.127:8180/geoserver/songbei/wms?', //这个可以打开geoserver的preview,看openlayer页面截取url // 请求参数 params: { 'SERVICE': 'WMS', 'VERSION': '1.1.0', 'REQUEST': 'GetMap', 'FORMAT': 'image/png', 'TRANSPARENT': true, 'tiled': true, 'LAYERS': 'songbei:songbei_map_layer1',//图层,前面是工作空间,后面是图层名, 'exceptions': 'application/vnd.ogc.se_inimage', 'singleTile': true//单瓦片,渲染成一张图片 } }), }), ]; //地图 var map = new ol.Map({ target: 'map', layers: layers, view: view }); // 添加工具图层,新增、修改、删除选择都在这个图层上进行 var source = new ol.source.Vector({ wrapX: false }); var vector = new ol.layer.Vector({ source: source, style: polygonStyleFunction }); map.addLayer(vector); // 仅以绘制面举例 var draw = new ol.interaction.Draw({ source: source, type: "Polygon" }); // 定义选择控件与修改控件 var select = new ol.interaction.Select({ wrapX: false }); var modify = new ol.interaction.Modify({ features: select.getFeatures() }); // 增删改查 变化时触发 var typeInteraction = document.getElementById('interaction'); typeInteraction.onchange = function() { map.removeInteraction(select); map.removeInteraction(modify); map.removeInteraction(draw); if (typeInteraction.value=='insert'){ map.addInteraction(draw); } if (typeInteraction.value=='modify'){ map.addInteraction(select); map.addInteraction(modify); } }; // 完成绘制(drawend)时激活 draw.once("drawend",function (e) { // draw工具不可用 draw.setActive(false); // 属性框 var tabletxt='<tr><td>' +'<input type="text" id="fid" value="fid" />'+'</td><td>' +'<input type="text" id="name" value="name" />'+'</td><td>' $("#attributetbody").append(tabletxt); }); // 点击按钮向geoserver提交数据 $("#creategml").click(function() { if (typeInteraction.value=='search'){ alert('支持insert update delete'); } // 获取feature列表 var features=source.getFeatures(); // 获取一个feature var feature=features[0]; var fid=$("#fid").val(); var name=$("#name").val(); console.log(name); // update和delete的时候需要fid feature.setId(fid); feature.set('name',name); // 创建WFS解析器 var WFSTSerializer = new ol.format.WFS(); var insertFeatures=[]; var updateFeatures=[]; var deleteFeatures=[]; if (typeInteraction.value=='insert'){ insertFeatures.push(feature); } if (typeInteraction.value=='modify'){ var updatefeature=select.getFeatures().getArray()[0]; updatefeature.setId(fid); updatefeature.set('name',name); updateFeatures.push(updatefeature); } if (typeInteraction.value=='delete'){ deleteFeatures.push(feature); } // 格式:writeTransaction(inserts, updates, deletes, options) // updates和deletes都需要要素有唯一ID,进行索引 // insert因为是新增,所以不需要 var featObject = WFSTSerializer.writeTransaction(insertFeatures, updateFeatures, deleteFeatures, { featureNS: 'http://geoserver.org/songbei',//工作区URI featurePrefix: 'songbei',//工作区名称 featureType: 'songbei:songbei_map_layer1',//图层名称 srsName: 'EPSG:4326',//坐标系 }); // 转换为xml内容发送到服务器端 var serializer = new XMLSerializer(); var featString = serializer.serializeToString(featObject); // 打印到控制台看看效果,openlayer默认生成的GML中几何字段名为geometry console.log(featString); // 清空属性表 $("#attributetable").html('<table><thead><tr><th>fid</th><th>name</th></tr></thead><tbody id="attributetbody"></tbody></table>'); // 上传到geoserver $.ajax({ type: 'POST', url: 'http://192.168.3.127:8180/geoserver/wfs', contentType:'text/xml', data: featString, dataType: 'xml', success: function(data){ console.log("正确") source.removeFeature(feature); console.log(data); }, error:function(data){ console.log("错误") source.removeFeature(feature); console.log(data); } }); }) //地图点击事件 $("#map").click(function (e) { if (typeInteraction.value=='insert'){ return; }; if (typeInteraction.value=='modify'){ return; }; if (typeInteraction.value=='delete'){ return; }; //获取地图上点击的地理坐标,WGS84坐标系 var t4326=map.getEventCoordinate(e); //构造请求url var param = `${t4326[0]-0.0001},${t4326[1]-0.0001},${t4326[0]+0.0001},${t4326[1]+0.0001},EPSG:4326`; //注意地址 var url4326=`http://192.168.3.127:8180/geoserver/wfs?request=GetFeature&version=1.1.0&typeName=songbei:songbei_map_layer1&outputFormat=application/json&BBOX=${param}`; console.log(url4326) //获取图层的id. $.ajax( { url:url4326, type:'GET', dataType:'json', headers:{'Content-Type':'application/json'}, success:function(data){ //这个方法直接把geojson转为feature数组 features=(new ol.format.GeoJSON()).readFeatures(data); // 将feature数组中第一个feature放到source中 source.addFeature(features[0]); //更新属性表 var fid=data['features'][0]['id']; var properties=data['features'][0]['properties']; var name=properties['name']; var name_ch=properties['name_ch']; var tabletxt='<tr><td>' +'<input type="text" id="fid" value="'+fid+'" />'+'</td><td>' +'<input type="text" id="name" value="'+name+'" />'+'</td><td>' $("#attributetbody").append(tabletxt); }, error:function(data){ console.log('faile'); console.log(data); } } ); }); //制图风格,标注内容要从要素中获取,每个要素的name_ch属性不同,所以制图风格是方法,而不是静态的 function polygonStyleFunction(feature) { return new ol.style.Style({ stroke: new ol.style.Stroke({ color: 'rgba(192, 0, 0, 1)', width: 2 }), fill: new ol.style.Fill({ color: 'rgba(192, 192, 192, 0.5)' }), text: createTextStyle(feature) }); }; //创建注记 function createTextStyle(feature) { return new ol.style.Text({ font: '20px Microsoft YaHei', text: getText(feature), fill: new ol.style.Fill({ color: 'rgba(192, 0, 0, 1)' }), stroke: new ol.style.Stroke({color: 'rgba(255, 255, 255, 1)', width: 1}), }) }; //获取要素属性内容 function getText(feature) { if (feature.get('name')){ return feature.get('name').toString(); } else{ return 'tool'; } }; </script> </body> </html>
执行之后就可以展示出来了,可以测试直接将页面地图点 线 面直接存到geoserver里。