GIS应用|快速开发REST数据服务
随着计算机的快速发展,GIS已经在各大领域得到应用,和我们的生活息息相关, 但是基于GIS几大厂商搭建服务,都会有一定的门槛,尤其是需要server,成本高,难度大,这里介绍一种在线GIS云平台,帮你快速解决服务端的问题,你只需要考虑自己客户端的业务层即可
SuperMap Online,可在线上传数据,发布多种REST服务,为您节省购买和部署SuperMap iServer的大量财力和时间成本,将数据和服务进行安全稳定的托管。
发布为REST数据服务的数据,可以通过少量代码开发来实现要素编辑即点、线、面数据的增删改查等功能。下面带领大家快速玩转REST数据服务!
要素编辑
(点击“在线演示”可在线查看)
01上传数据,发布服务,在线安全托管
打开SuperMap Online并登录您的账号,依次点击“资源中心”-“数据”-“上传数据”。
上传数据
选择数据类型并进行上传。本示例使用的是SuperMap工作空间数据—“china.zip”。(示例数据百度云下载链接: https://pan.baidu.com/s/17gsAySUvb_nbsYWHQi4UHQ 提取码: h845 )。
选择数据并上传
云存储支持将上传的数据发布为地图、数据、三维、空间分析等多种类型的REST服务。本示例选择发布的服务类型为“REST数据服务”。
选择服务类型并发布
发布完成后的数据可以在“资源中心”-“数据”-“我的数据”查看。调用服务前需要开启数据共享。点击服务名称下对应服务地址,选择目标目录复制链接即可调用该REST数据服务,数据服务的子资源在 SuperMap iServer中是数据查询和操作的入口,提供了数据源集合和数据查询功能的资源信息。
修改数据权限,打开REST数据服务
选择目标目录
获取REST数据服务地址
REST数据服务也可以通过使用“密钥key”的方式来进行调用,搜索并打开SuperMap Online,在首页下方找到开发模块,更多服务调用方式等你发现!
SuperMap Online首页开发模块
02调用REST数据服务,实现数据修改功能
获取服务地址后,即可在网页中调用REST数据服务。示例中,底图调用的是REST地图服务,点击可查看REST地图服务使用方法哦!
调用REST数据服务
通过简单代码编写,可以对REST数据服务进行编辑。如已知某点坐标,即可以直接在REST数据服务中添加该点。
新增点数据
REST数据服务也可以用于打造在线数据编辑平台,可以实现点、线、面要素的增删改查,修改后的结果可以同步到REST数据服务当中。
要素编辑
源码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> <link href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/css/ol.css" rel="stylesheet" /> <link href='https://iclient.supermap.io/dist/ol/iclient-ol.min.css' rel='stylesheet' /> <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.4.3/build/ol.js"></script> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript" src="https://iclient.supermap.io/dist/ol/iclient-ol.min.js"></script> <link href='https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' /> <script type="text/javascript" src="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> <script type="text/javascript" src="https://iclient.supermap.io/examples/js/widgets.js"></script> <title>地物编辑</title> <style> .ol-zoom { bottom: .5em; font-size: 18px; top: unset; } .editPane { position: absolute; left: 15px; top: 8px; text-align: center; background: #FFF; z-index: 1000; border-radius: 4px; } .ol-popup { position: absolute; background-color: white; -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); padding: 15px; border-radius: 10px; border: 1px solid #cccccc; bottom: 12px; left: -50px; min-width: 120px; } .ol-popup:after, .ol-popup:before { top: 100%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none; } .ol-popup:after { border-top-color: white; border-width: 10px; left: 48px; margin-left: -10px; } .ol-popup:before { border-top-color: #cccccc; border-width: 11px; left: 48px; margin-left: -11px; } .tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; } @media only screen and (max-width: 640px) { #msg_container { transform: translate(-35%, -20%); } } </style> </head> <body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%; position: absolute;top: 0;"> <div id="map" style="width: 100%;height:100%"></div> <div id="popup" class="ol-popup"> <div id="popup-content"></div> </div> <div> <div class="panel panel-primary editPane" id="editPane"> <div class='panel-heading'> <h5 class='panel-title text-center'>编辑单个要素</h5> </div> <div class='panel-body content'> <input type='button' class='btn btn-default' value="添加地物" onclick='addMarker()' /> <input type='button' class='btn btn-default' value="撤销添加" onclick='revocationMarker()' /> <input type='button' class='btn btn-default' value="提交" onclick='commit()' /> <input type='button' class='btn btn-default' value="修改" onclick='clearLayer(selectFeaturForUpdate)' /> <input type='button' class='btn btn-default' value="清除" onclick='clearLayer(selectFeatureForDelete)' /> </div> </div> </div> <div id="pointInfoModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="largerModal"> <div class="modal-dialog modal-sm" role="document"> <div class="modal-content"> <div class="modal-header">输入新增点名字</div> <div class="modal-body"> <input type="text" class="form-control" id="point-info" autocomplete="off"> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal" onclick="revocationMarker()">取消</button> <button type="button" class="btn btn-primary" onclick="setPointName()">确定</button> </div> </div> </div> </div> <div class="modal fade" id="updatePointModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> <div class="modal-dialog modal-sm"> <div class="modal-content" style="width: 400px;"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"> × </button> <h4 class="modal-title" id="myModalLabel"> 要素信息 </h4> </div> <div class="modal-body"> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="name" class="col-sm-3 control-label" style="width: 21%;">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" id="name" name="name" value=""> </div> </div> <div class="form-group"> <label for="x" class="col-sm-3 control-label" style="width: 21%;">X(m)</label> <div class="col-sm-9"> <input type="text" class="form-control" name="x" value="" id="x"> </div> </div> <div class="form-group"> <label for="y" class="col-sm-3 control-label" style="width: 21%;">Y(m)</label> <div class="col-sm-9"> <input type="text" class="form-control" name="y" value="" id="y"> </div> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button> <button type="submit" class="btn btn-primary" onclick="updateFeature()">修改</button> </div> </div> </div> </div> <div class="modal fade" id="confirmModel"> <div class="modal-dialog"> <div class="modal-content message_align" style="width: 400px;"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title">确认信息</h4> </div> <div class="modal-body"> <p id="delcfmMsg">您确认要删除吗?</p> </div> <div class="modal-footer"> <input type="hidden" id="submitUrl" /> <button type="button" class="btn btn-default" data-dismiss="modal">取消</button> <a onclick="deleteFeature()" class="btn btn-success" data-dismiss="modal">确定</a> </div> </div> </div> </div> <script type="text/javascript"> var map, draw, pointFeature, vectorSource, resultLayer, addPointsSource, addPointsLayer, func, update, deletedId, helpTooltipElement, helpTooltip, isclearPoint, baseMap = "https://maptiles.supermapol.com/iserver/services/map_China/rest/maps/China_Dark", //替换为在online上发布的数据服务,需要设置为公开 dataService = "https://www.supermapol.com/proxy/iserver/services/data_china_54y8bdc4/rest/data", editFeaturesService = new ol.supermap.FeatureService(dataService), container = document.getElementById('popup'), content = document.getElementById('popup-content'), pointName = document.getElementById('point-info'), overlay = new ol.Overlay(({ element: container, autoPan: true, autoPanAnimation: { duration: 250 }, offset: [0, -20] })), map = new ol.Map({ target: 'map', controls: ol.control.defaults({ attributionOptions: { collapsed: true } }) .extend([]), view: new ol.View({ center: [12962344.405822188, 4830679.745330002], zoom: 5, projection: 'EPSG:3857', multiWorld: true }), }); var layer = new ol.layer.Tile({ source: new ol.source.TileSuperMapRest({ url: baseMap }), projection: 'EPSG:3857' }); map.addLayer(layer); createHelpTooltip(); initFeature(); loadLayer(); //创建鼠标操作提示 function createHelpTooltip() { if (helpTooltipElement) { helpTooltipElement.parentNode.removeChild(helpTooltipElement); } helpTooltipElement = document.createElement('div'); helpTooltipElement.className = 'tooltip hidden'; helpTooltip = new ol.Overlay({ element: helpTooltipElement, offset: [15, 0], positioning: 'center-left' }); } //查询数据,页面初始化显示 function initFeature() { var getFeatureParams = new SuperMap.GetFeaturesBySQLParameters({ //查询参数,根据自己的服务设置参数 queryParameter: { name: "CityA_P@China", orderBy: "SMID desc" }, datasetNames: ["China:CityA_P"], fromIndex: 0, toIndex: 30 }); editFeaturesService.getFeaturesBySQL(getFeatureParams, function(serviceResult) { var features = (new ol.format.GeoJSON()).readFeatures(serviceResult.result.features); for (var i = 0; i < features.length; i++) { features[i].setStyle(new ol.style.Style({ image: new ol.style.Icon(({ anchor: [0.5, 0.9], src: 'https://iclient.supermap.io/examples/img/markerbig_select.png' })) })); } //避免重复添加图层,只对一个图层进行数据更新操作: if (vectorSource.getFeatures().length > 0) { vectorSource.clear(); } vectorSource.addFeatures(features); map.on('pointermove', pointermoveLinstener); }); } //添加图层 function loadLayer() { //添加查询结果图层 vectorSource = new ol.source.Vector({ wrapX: false }); resultLayer = new ol.layer.Vector({ source: vectorSource, }); //添加点图层 addPointsSource = new ol.source.Vector({ wrapX: false }); addPointsLayer = new ol.layer.Vector({ source: addPointsSource, }); map.addLayer(addPointsLayer); map.addLayer(resultLayer); } //鼠标移动监听,移动到点上显示名字 function pointermoveLinstener(e) { var select = false; map.forEachFeatureAtPixel(e.pixel, function(feature) { if (feature.getProperties().NAME) { map.getTargetElement().style.cursor = 'pointer'; var contentHTML = feature.getProperties().NAME; content.innerHTML = contentHTML; overlay.setPosition(feature.getGeometry().getCoordinates()); map.addOverlay(overlay); select = true } }, { hitTolerance: 10 }); if (!select) { map.getTargetElement().style.cursor = ''; overlay.setPosition(undefined); map.removeOverlay(overlay); } if (isclearPoint) { helpTooltipElement.innerHTML = '选择要操作的要素'; helpTooltip.setPosition(e.coordinate); helpTooltipElement.classList.remove('hidden'); map.addOverlay(helpTooltip); } else { helpTooltip.setPosition(undefined); helpTooltipElement.classList.add('hidden'); } } //添加标记点 function addMarker() { if (isclearPoint) { closeSelectListener(func); } widgets.alert.clearAlert(); if (!pointFeature) { ceateMarker() } else { addPointsSource.clear(); ceateMarker() } //通过点击创建标记点 function ceateMarker() { draw = new ol.interaction.Draw({ source: addPointsSource, type: 'Point' }); map.addInteraction(draw); draw.on("drawstart", function(e) { pointFeature = e.feature; pointFeature.setStyle(new ol.style.Style({ image: new ol.style.Circle({ fill: new ol.style.Fill({ color: [255, 0, 0, 0.5] }), stroke: new ol.style.Stroke({ color: 'red', width: 2 }), radius: 8 }) })); addPointsSource.addFeature(pointFeature); map.removeInteraction(draw); $('#pointInfoModal').modal({ backdrop: 'static', keyboard: false, show: true }) $('#pointInfoModal').on('shown.bs.modal', function() { $("#pointInfoModal #point-info").focus(); }); }); } } //设置添加点的名字 function setPointName() { pointFeature.setProperties({ "NAME": pointName.value }); $('#point-info').val(""); $('#pointInfoModal').modal('hide'); } //撤销添加,清除标绘点 function revocationMarker() { if (pointFeature) { addPointsSource.clear(); pointFeature = null; } else { widgets.alert.showAlert('没有可撤回的要素。', false); } } //提交新增点到数据服务 function commit() { widgets.alert.clearAlert(); if (pointFeature) { //新增点要素参数,根据自己的服务设置参数 var addFeatureParams = new SuperMap.EditFeaturesParameters({ features: pointFeature, dataSourceName: "China", dataSetName: "CityA_P", editType: "add", returnContent: true }); editFeaturesService.editFeatures(addFeatureParams, function(serviceResult) { if (serviceResult.result.succeed) { addPointsSource.clear(); vectorSource.clear(); pointFeature = null; initFeature(); widgets.alert.showAlert('提交成功', true); } }); } else { widgets.alert.showAlert('没有可提交的新要素,请先添加新要素。', false); } } //地图点击事件,选择点进行修改或删除 function clearLayer(method) { widgets.alert.clearAlert(); isclearPoint = true; map.on('click', method); func = method; } //选择要素修改 function selectFeaturForUpdate(e) { if (isclearPoint) { closeSelectListener(func); } update = null; widgets.alert.clearAlert(); map.forEachFeatureAtPixel(e.pixel, function(feature) { //只修改选中第一个要素: if (!update) { update = feature; var coordinate = feature.getGeometry().getCoordinates(); var name = feature.getProperties().NAME; $('#name').val(name); $('#x').val(coordinate[0]); $('#y').val(coordinate[1]); $('#updatePointModal').modal({ backdrop: 'static', keyboard: false, show: true }) } }, { hitTolerance: 1 }); } //修改要素,更新数据服务 function updateFeature() { $('#updatePointModal').modal('hide'); var name = document.getElementById('name').value; var x = document.getElementById('x').value; var y = document.getElementById('y').value; update.getGeometry().setCoordinates([x, y]); update.setProperties({ "NAME": name }); //修改要素参数,根据自己的服务设置参数 var updateParams = new SuperMap.EditFeaturesParameters({ dataSourceName: "China", dataSetName: "CityA_P", features: update, editType: "update" }); editFeaturesService.editFeatures(updateParams, function(serviceResult) { if (serviceResult.result.succeed) { initFeature(); vectorSource.clear(); isclearPoint = false; closeSelectListener(selectFeaturForUpdate); widgets.alert.showAlert('更新成功', true); } else { widgets.alert.showAlert('更新失败', false) } }); } //选择要素删除 function selectFeatureForDelete(e) { if (isclearPoint) { closeSelectListener(func); } deletedId = null; map.forEachFeatureAtPixel(e.pixel, function(feature) { //只删选中第一个要素: if (!deletedId) { deletedId = feature.getId(); //避免示例数据被删除,只允许删除额外添加的点 if (deletedId > 269) { $('#confirmModel').modal({ backdrop: 'static', keyboard: false, show: true }) } else { widgets.alert.showAlert('为保持示例数据完整性,请先添加一个点来进行删除操作', false) } } }, { hitTolerance: 1 }); } //删除要素,更新数据服务 function deleteFeature() { //删除要素参数,根据自己的服务设置参数 var deleteParams = new SuperMap.EditFeaturesParameters({ dataSourceName: "China", dataSetName: "CityA_P", IDs: [deletedId], editType: "delete" }); editFeaturesService.editFeatures(deleteParams, function(serviceResult) { if (serviceResult.result.succeed) { initFeature(); vectorSource.clear(); isclearPoint = false; closeSelectListener(selectFeatureForDelete); widgets.alert.showAlert('删除要素成功!', true); } else { widgets.alert.showAlert('删除要素失败!', false) } }); } //关闭地图点击事件,移除鼠标提示 function closeSelectListener(method) { isclearPoint = false; map.un('click', method); helpTooltip.setPosition(undefined); map.removeOverlay(helpTooltip); helpTooltipElement.classList.add('hidden'); } </script> </body> </html>
REST数据服务不仅可以通过简单开发实现数据编辑、查询等功能,也可以直接在云应用中通过“添加服务”的方式进行使用。本篇文章以REST数据服务为例,通过云存储还可以发布地图、三维、空间分析等多种类型的REST服务,点击可查看REST地图服务使用方法,后续会发布更多关于REST服务使用的相关文章,还请大家多多关注哦!