上一篇《ArcGIS Server 10.2 實戰(一)Asp.net MVC與JSON數據妙用實現動態生成要素圖層》介紹了如何用JSON轉要素的地理處理服務,實現了動態創建點要素並加載到相應的地圖上,但是對於線、面要素,由於動態生成時需要較大的JSON數據,這個方法就不太合適了,下面介紹另一個可行的方法,用動態的方法修改現有面要素的指定字段數據。
首先還是先談談問題的背景,需要制作一個專題地圖,用於對於各塊地域的數據進行分級填色,每天都有一套數據對應有一個專題地圖,同樣不可能每天都制作圖層和發布,因此需要圖層中的數據可根據從外部數據源的查詢到的數據動態的變化。好,下面就來解決這個問題。
飲水思源,轉載勿刪:http://www.cnblogs.com/evkchina/p/3435573.html,請支持關注北京易維清www.evkchina.com
![]() |
![]() |
1.創建ArcGIS模型:用數據管理工具》字段》計算字段,設置輸入表、字段名、表達式、表達式類型(采用PYTHON_9.3)和代碼塊,其中表達式(expressionP)和代碼塊(codeblockP)為模型參數,流域排放總量等級作為模型參數並勾選添加至顯示。
2.地理處理服務的發布在《ArcGIS Server 10.2 實戰(一)Asp.net MVC與JSON數據妙用實現動態生成要素圖層》中已經略有介紹,就不細說了。
3.在javascript中使用地理處理服務:調用發布的javascript代碼為,具體代碼解讀可以參照Arcgis官網給出的例子(https://developers.arcgis.com/en/javascript/jssamples/gp_resultmapservice.html)。

<script type="text/javascript"> require([ "dojo/dom", "dojo/_base/array", "dojo/date/locale", "dojo/parser", "dijit/registry", "esri/domUtils", "esri/map", "esri/graphic", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/FeatureLayer", "esri/tasks/Geoprocessor", "esri/dijit/Legend", "dijit/form/DateTextBox", "dijit/layout/BorderContainer", "dijit/layout/ContentPane"], function (dom, array, locale, parser, registry, domUtils, Map, Graphic, ArcGISDynamicMapServiceLayer, FeatureLayer, Geoprocessor, Legend) { var gpServiceUrl = "http://huang-pc:6080/arcgis/rest/services/dianchi/liuyuZL/GPServer/liuyuZL", mapserviceurl = "http://huang-pc:6080/arcgis/rest/services/dianchi/liuyuZL/MapServer/jobs", legend; parser.parse(); var map = new Map("map", { basemap: "satellite", center: [102.7038, 24.8270], logo: false, zoom: 11 }); var riversLayer = new ArcGISDynamicMapServiceLayer("http://huang-pc:6080/arcgis/rest/services/dianchi/rivers/MapServer", { "id": "rivers" }); //Run the gp task when the app loads to display default incidents // map.on("load", findHotspot); function findHotspot() { //cleanup any results from previous runs cleanup(); mysubmitJob(); } function cleanup() { //hide the legend and remove the existing hotspot layer domUtils.hide(dom.byId('legendDiv')); var hotspotLayer = map.getLayer('HotspotLayer'); if (hotspotLayer) { map.removeLayer(hotspotLayer); map.removeLayer(map.getLayer('rivers')); } } var jobs = 0; var jobstatus = ""; var interval; function mysubmitJob() { var thedate = $("#theDate").val(); var wq = $("#dataType").val(); $.ajax({ type: "POST", url:"@Url.Action("R2GISViewLYcodeblockP", "Home")", data:{"year" : thedate, "wq" : wq}, success:function (data) { var codeblockp = data.codeblockP; $("#lastdate").text("當年總量累加至" + data.lastDate); var submitjoburl = gpServiceUrl + "/submitJob"; $.ajax({ type: 'get', dataType: "jsonp", url: submitjoburl, data: { codeblockP: codeblockp, expressionP: "setData ( !DSN! )", f: "pjson" }, jsonpCallback: "jsonpCallback", success: function (data) { jobs = 0; if (data.jobStatus == "esriJobSucceeded") { doMapJob(data); } else { getJobStatus(data.jobId); } } }); } }); } function getJobStatus(sjobid) { clearTimeout(interval); domUtils.show(dom.byId('status')); if (jobs < 60) { var sjoburl = gpServiceUrl + "/jobs/" + sjobid; $.ajax({ type: "get", dataType: "jsonp", url: sjoburl, data: { f: "pjson" }, jsonpCallback: "jsonpCallback", success: function (data) { switch (data.jobStatus) { case 'esriJobSubmitted': jobstatus = '已提交...'; dom.byId('status').innerHTML = jobstatus; jobs = jobs + 1; interval = setTimeout(function () { getJobStatus(data.jobId) }, 1000); break; case 'esriJobExecuting': jobstatus = '處理中...'; dom.byId('status').innerHTML = jobstatus; jobs = jobs + 1; interval = setTimeout(function () { getJobStatus(data.jobId) }, 1000); break; case 'esriJobSucceeded': clearTimeout(interval); domUtils.hide(dom.byId('status')); doMapJob(data); break; case 'esriJobFailed': clearTimeout(interval); jobstatus = '查詢失敗'; dom.byId('status').innerHTML = jobstatus; gpJobFailed(); } } }); } else { clearTimeout(interval); jobstatus = '查詢失敗'; dom.byId('status').innerHTML = jobstatus; gpJobFailed(); } } function gpJobFailed() { //domUtils.hide(dom.byId('status')); } function doMapJob(jobinfo) { //construct the result map service url using the id from jobinfo we'll add a new layer to the map var mapurl = mapserviceurl + "/" + jobinfo.jobId; var hotspotLayer = new ArcGISDynamicMapServiceLayer(mapurl, { "id": "HotspotLayer", "opacity": 1 }); //add the hotspot layer to the map map.addLayers([hotspotLayer]); map.addLayers([riversLayer]); map.on("layers-add-result", function (evtObj) { domUtils.show(dom.byId('legendDiv')); if (!legend) { //add the legend to show the resulting layer. var layerInfo = array.map(evtObj.layers, function (layer, index) { return { layer: layer.layer, title: "結果圖層" }; }); legend = new Legend({ map: map, layerInfos: layerInfo }, "legendDiv"); legend.startup(); } }); } app = { findHotspot: findHotspot }; return app; }); </script>
其中,function mysubmitJob()中的"@Url.Action("R2GISViewLYcodeblockP", "Home")"是Asp.net MVC中的寫法,是異步調用URL home/R2GISViewLYcodeblockP,返回代碼塊的內容,而且這里不必要使用跨域的寫法,一般ajax異步就可以,方法代碼如下

public ActionResult R2GISViewLYcodeblockP(int year, string wq) { var codeblockp = new LiuYUData().getZLData(year, wq); JsonResult jsonData = new JsonResult { Data = codeblockp }; return Json(jsonData.Data); }
另外,代碼塊內容(string)的生成代碼為,強調一下,經過實踐,這里面的空格對代碼塊的影響比較大,可能是PYTHON_9.3的問題,需要大家嚴重注意。

public LYData getZLData(int year, string wq) { var lydata = new LYData(); lydata.lastDate = "(無數據累加)"; string zldata = ""; var zls = db.R2_WQs.Where(m => m.DateTime.Value.Year == year && m.Object == wq + " 年總量").ToList(); if (zls.Count > 0) { zldata = "def setData ( dsn ):\n"; foreach (var zl in zls) { zldata = zldata + " if dsn == " + "\"" + zl.DSNID.Substring(0, zl.DSNID.Length - 2) + "\":\n" + " return " + zl.ZLWarn.ToString() + "\n"; } zldata = zldata + " else:\n return 0"; lydata.codeblockP = zldata; lydata.lastDate = zls[0].DateTime.Value.ToString("yyyy年MM月dd日", DateTimeFormatInfo.InvariantInfo); } return lydata; }
飲水思源,轉載勿刪:http://www.cnblogs.com/evkchina/p/3429793.html,請支持關注北京易維清www.evkchina.com
到此為止,問題就結束了。
由於時間關系,很多具體的細節沒有在這里說到,請見諒,歡迎在本文評論中交流學習。
這里是用計算字段的代碼塊來對圖層要素進行動態修改數據內容,感覺這種方法很笨重奇怪,但是尋找了很久也沒有一個好的接口根據外部數據動態修改圖層要素數據,有沒有別的更簡便的方法呢,請各位大神指教。