ArcGIS API for JavaScript 4.2学习笔记[27] 网络分析之最短路径分析【RouteTask类】
要说网页端最经典的GIS应用,非网络分析莫属了。
什么?你没用过?百度高德谷歌地图的路线分析就是活生生的例子啊!只不过它们是根据大实际背景优化了结果显示而已。
这个例子使用RouteTask进行网络分析,我会先讲讲什么是RouteTask,再讲讲这个例子是怎么用的,这个例子代码量不多。
在官方的例子中,标题为:SimpleRouting - RouteTask
看看结果
点击两个点,安静等待十秒左右就会出现这个紫色的路线了。当然右键点击也是一样的。反应比较慢。
RouteTask类
这个例子用到了这个类,务必先介绍一下,因为在上一章中已经介绍了三个用于查询的Task类了。
介绍上说,RouteTask允许用户在AJS中方便地在给定的点上进行最短路径查询,RouteTask使用ArcGIS Server发布的网络分析服务(NAServer)。
有关ArcGIS Server如何发布NAServer,我会在我另一个系列中写一写。
这就说明了RouteTask是使用Server的REST URL进行实例化的。
它最常用的是solve()方法。(与AO二次开发类似)
同样的,它也有对应的RouteParameters和RouteResult类。
RouteParameters和RouteResult类
这个参数类拥有网络分析特有的属性:如途径点、障碍点、阻抗属性等,见桌面GIS网络分析的文档。
RouteTask的返回结果。取决于RouteParameters的参数设置。
好,咱们正式开始吧。
给出引用
require([ "esri/Map", "esri/views/MapView", "esri/Graphic", "esri/layers/GraphicsLayer", "esri/tasks/RouteTask", "esri/tasks/support/RouteParameters", "esri/tasks/support/FeatureSet", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol", "esri/Color", "esri/core/urlUtils", "dojo/on", "dojo/domReady!" ], function(Map, MapView, Graphic, GraphicsLayer, RouteTask, RouteParameters, FeatureSet, SimpleMarkerSymbol, SimpleLineSymbol, Color, urlUtils, on) { ... } );
用到的模块很多。
函数骨架
function(...){ urlUtils.addProxyRule({...}); var routeTask = new RouteTask({ url: "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World" }); var routeLyr = new GraphicsLayer(); var routeParams = new RouteParameters({...}); var stopSymbol = new SimpleMarkerSymbol({...}); var routeSymbol = new SimpleLineSymbol({...}); var map = new Map({...}); var view = new MapView({...}); on(view, "click", addStop); function addStop(event){...}; function showRoute(event){...}; )
重点应该是routeTask、routeParams这两个变量,和view的click事件、addStop()方法、showRoute()方法。
两个变量用于执行网络分析中的最短路径分析,而事件和方法就进行对分析结果的处理和显示。
routeTask使用了NAServer,这是一个ArcGIS Server的服务,参考Server的文档即可。
urlUtils类和addProxyRule是什么?查询API得知:这是个对url进行管理设置的一个类,addProxyRule好像是添加一条代理设置。//有待考究,删除是否可以执行网络分析。
两个符号:stopSymbol和routeSymbol是点击出现的十字点符号和路径分析结果的紫色线。
所以重点就放在了routeParams、view的click事件和两个方法体上:
routeParams对象
var routeParams = new RouteParameters({ stops: new FeatureSet(), outSpatialReference: { wkid: 3857 } });
stops是RouteParameters类的一个属性,其类型为DataLayer或者FeatureSet。
意义是:进行网络分析时所需要的途径点集合。
在这里,直接实例化了一个FeatureSet对象,不过是空对象。
click事件和2个方法体
on(view, "click", addStop); function addStop(event) { var stop = new Graphic({ geometry: event.mapPoint, symbol: stopSymbol }); routeLyr.add(stop); routeParams.stops.features.push(stop); if (routeParams.stops.features.length >= 2) { routeTask.solve(routeParams).then(showRoute); } } function showRoute(data) { var routeResult = data.routeResults[0].route; routeResult.symbol = routeSymbol; routeLyr.add(routeResult); }
视图的点击事件,即addStop方法。
首先会产生一个新的图形对象,其geometry属性赋值为了:点击的点位置对应的Point对象(在事件流中)。
符号则用上方定义的点符号/
然后把这个图形对象stop添加到routeLyr这个图形图层中。
紧接着,把这个图形对象传递给routeParams。它最终传递到了哪里?
刚刚说了,stops给了一个FeatureSet对象,FeatureSet对象则拥有一个features属性(类型为Graphic[]),将刚刚实例化的stop对象push进去。
这样,RouteTask所需的RouteParameters中就多了一个需要停靠的点的信息。
然后,判断停靠点的数量是否大于等于2(两点才能始终嘛)
如果>=2,那么执行routeTask的solve方法,接着一个异步操作,回调函数为showRoute()。
showRoute()方法的作用是获取传入参数data的routeResults属性(其为routeResults[]类型)的第一个元素,即RouteResult对象。//data类型未知,查不到,应该是solve的回传。但是官方写着solve的返回值是RouteResult的实例...
然后把这个RouteResult对象的route属性获取,并设置其符号为上方实例化的线符号,加入到routeLyr图形图层中。
——————
总结一下
符号、图层、地图、场景都是老生常谈了。
最重要的部分即view的click事件,所触发的所有信息,包括RouteParameters对象的属性设置、RouteTask对象的solve方法的使用及RouteResult对象的数据处理。
点击视图——获取点位——设置RouteParameters对象——执行RouteTask.solve()——处理RouteResult对象。
最后给出完整代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> <title>Simple Routing - RouteTask - 4.2</title> <style> html, body, #viewDiv { padding: 0; margin: 0; height: 100%; width: 100%; } #paneDiv { position: absolute; top: 10px; left: 62px; padding: 0 12px 0 12px; background-color: rgba(0, 0, 0, 0.5); color: white; } </style> <link rel="stylesheet" href="https://js.arcgis.com/4.2/esri/css/main.css"> <script src="https://js.arcgis.com/4.2/"></script> <script> require([ "esri/Map", "esri/views/MapView", "esri/Graphic", "esri/layers/GraphicsLayer", "esri/tasks/RouteTask", "esri/tasks/support/RouteParameters", "esri/tasks/support/FeatureSet", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol", "esri/Color", "esri/core/urlUtils", "dojo/on", "dojo/domReady!" ], function( Map, MapView, Graphic, GraphicsLayer, RouteTask, RouteParameters, FeatureSet, SimpleMarkerSymbol, SimpleLineSymbol, Color, urlUtils, on ) { // proxy the route requests to avoid prompt for log in urlUtils.addProxyRule({ urlPrefix: "route.arcgis.com", proxyUrl: "/sproxy/" }); // Point the URL to a valid route service var routeTask = new RouteTask({ url: "https://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World" }); // The stops and route result will be stored in this layer var routeLyr = new GraphicsLayer(); // Setup the route parameters var routeParams = new RouteParameters({ stops: new FeatureSet(), outSpatialReference: { // autocasts as new SpatialReference() wkid: 3857 } }); // Define the symbology used to display the stops var stopSymbol = new SimpleMarkerSymbol({ style: "cross", size: 15, outline: { // autocasts as new SimpleLineSymbol() width: 4 } }); // Define the symbology used to display the route var routeSymbol = new SimpleLineSymbol({ color: [0, 0, 255, 0.5], width: 5 }); var map = new Map({ basemap: "streets", layers: [routeLyr] // Add the route layer to the map }); var view = new MapView({ container: "viewDiv", // Reference to the scene div created in step 5 map: map, // Reference to the map object created before the scene center: [-117.195, 34.057], zoom: 14 }); // Adds a graphic when the user clicks the map. If 2 or more points exist, route is solved. on(view, "click", addStop); function addStop(event) { // Add a point at the location of the map click var stop = new Graphic({ geometry: event.mapPoint, symbol: stopSymbol }); routeLyr.add(stop); // Execute the route task if 2 or more stops are input routeParams.stops.features.push(stop); if (routeParams.stops.features.length >= 2) { routeTask.solve(routeParams).then(showRoute); } } // Adds the solved route to the map as a graphic function showRoute(data) { var routeResult = data.routeResults[0].route; routeResult.symbol = routeSymbol; routeLyr.add(routeResult); } }); </script> </head> <body> <div id="viewDiv"></div> <div id="paneDiv"> <div> <p>Click on the map to add stops to the route. The route from the last stop to the newly added stop is calculated. If a stop is not reachable, it is removed and the last valid point is set as the starting point.</p> </div> </div> </body> </html>