config.xml文件的配置如下:
<widget label="路径导航" icon="assets/images/lujingdaohang.png"
config="widgets/eDriections/eDirectionsWidget.xml" url="widgets/eDriections/eTabDirectionsWidget.swf" />
源代码目录如下:
界面效果:
大概的思路如下:1.文本框输入开始点以及结束点,获取两个点坐标;2.直接在地图上点击两个点,获取两个点坐标;其实两个的最终目的是一样的,都是为了获取两个点坐标。其中用到了地理编码服务,用于根据地名来获取坐标以及根据坐标来获取地名信息。
用到了arcgis api的最短路径分析接口,routeParams以及routeTask,routeParams用来设置一些关于路径分析的参数,routeTask是用来执行路径分析方法的,具体的要看看api的介绍才行。备注:该功能模块的核心前提是要发布网络分析服务,这个在我的博客其他文章有写的
总的来说,获取两个点坐标,保存在一个stops数组里面,然后设置routeParams的属性,routeParams对象有个属性是stops,除了stops之外,还有attributeParameterValues、directionsLengthUnits、returnDirectionsreturnDirections、returnRoutes、returnStops等等;最好是执行routeTask.solve(routeParams);
eDirectionsWidget.xml:配置一些路径分析的信息
<?xml version="1.0" ?>
<configuration>
<url>http://localhost:6080/ArcGIS/rest/services/gzRoad/NAServer/路径</url>
<useproxy>false</useproxy>
<!-- <locatorurl>http://172.16.6.67/ArcGIS/rest/services/guangzhou_loc/GeocodeServer</locatorurl> -->
<locatorurl>http://localhost:6080/ArcGIS/rest/services/ns_loc_Composite/GeocodeServer</locatorurl>
<routeoptions />
<fromTx>广州市南沙区信访局</fromTx>
<toTx>小虎一桥</toTx>
</configuration> <!-- See Directions widget tag reference at http://links.esri.com/directionswidget -->
eTabDirectionsWidget.mxml:
<?xml version="1.0" encoding="utf-8"?>
<!--
///////////////////////////////////////////////////////////////////////////
// Copyright (c) 2013 Esri. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////
-->
<viewer:BaseWidget xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:viewer="com.esri.viewer.*"
xmlns:esri="http://www.esri.com/2008/ags"
xmlns:RichTabNavigator="com.RichTabNavigator.*"
initialize="basewidget_initializeHandler(event)"
widgetConfigLoaded="basewidget_widgetConfigLoaded()">
<viewer:states>
<s:State name="textInput"/>
<s:State name="resultsList"/>
</viewer:states> <viewer:transitions>
<s:Transition autoReverse="true" toState="*">
<s:Fade id="fade"/>
</s:Transition>
</viewer:transitions>
<fx:Script>
<![CDATA[
import com.esri.ags.FeatureSet;
import com.esri.ags.Graphic;
import com.esri.ags.SpatialReference;
import com.esri.ags.events.DrawEvent;
import com.esri.ags.events.LocatorEvent;
import com.esri.ags.events.RouteEvent;
import com.esri.ags.geometry.Extent;
import com.esri.ags.geometry.Geometry;
import com.esri.ags.geometry.MapPoint;
import com.esri.ags.geometry.Polyline;
import com.esri.ags.portal.PopUpRenderer;
import com.esri.ags.portal.supportClasses.PopUpInfo;
import com.esri.ags.symbols.TextSymbol;
import com.esri.ags.tasks.supportClasses.AddressCandidate;
import com.esri.ags.tasks.supportClasses.AddressToLocationsParameters;
import com.esri.ags.tasks.supportClasses.DirectionsFeatureSet;
import com.esri.ags.tasks.supportClasses.NAOutputLine;
import com.esri.ags.tasks.supportClasses.RouteResult; import mx.collections.ArrayCollection;
import mx.containers.Panel;
import mx.containers.TitleWindow;
import mx.controls.Alert;
import mx.controls.Text;
import mx.controls.TextArea;
import mx.core.IVisualElement;
import mx.core.UIComponent;
import mx.events.CloseEvent;
import mx.events.EffectEvent;
import mx.events.FlexEvent;
import mx.events.ListEvent;
import mx.events.ModuleEvent;
import mx.events.ResizeEvent;
import mx.formatters.*;
import mx.managers.PopUpManager;
import mx.rpc.AsyncResponder;
import mx.rpc.Fault;
import mx.rpc.events.FaultEvent; import spark.components.NavigatorContent;
import spark.events.IndexChangeEvent;
import spark.primitives.Path; private const ICON_URL:String = "assets/images/";
private var textsearchLabel:String="路径分析";
private var resultsLabel:String="分析结果";
[Bindable]
private var fromText:String;
[Bindable]
private var toText:String;
protected function basewidget_initializeHandler(event:FlexEvent):void
{
if (isPartOfPanel) // if widget is part of "left", "right" or "bottom" panel
{
this.percentWidth = this.percentHeight = 100;
wTemplate.percentWidth = wTemplate.percentHeight = 100;
}
else
{
wTemplate.height = map.height - map.height / 100 - Number(this.top) - Number(this.bottom);
wTemplate.width = 440;
}
} private function basewidget_widgetConfigLoaded():void
{
// hide map infowindow if any
map.infoWindow.hide();
if (configXML)
{
sUrl = configXML.url[0];
var useProxyForDirections:Boolean = configXML.useproxy[0] && configXML.useproxy == "true";
locatorURL = configXML.locatorurl[0];
fromText=configXML.fromTx[0];
toText=configXML.toTx[0];
}
wTemplate.addTitlebarButton(ICON_URL + "i_searchtext.png", textsearchLabel, showStateTextSearch);
wTemplate.addTitlebarButton(ICON_URL + "i_table.png", resultsLabel, showStateResults);
fade.targets = [ textInput, resultsList ];
wTemplate.visible = true;
} private function showStateTextSearch():void
{
this.currentState = "textInput";
wTemplate.selectedTitlebarButtonIndex = 0;
} private function showStateResults():void
{
this.currentState = "resultsList";
wTemplate.selectedTitlebarButtonIndex = 1;
} //////////////////////////////////////////////////////
//路径分析功能部分代码
[Bindable]
private var sUrl:String;//="http://172.16.6.67/ArcGIS/rest/services/gzRoad/NAServer/路径";
[Bindable]
private var locatorURL:String;
private var stopType:String;
private var fromGraphic:Graphic;
private var toGraphic:Graphic;
[Bindable]
private var startTime:Date=new Date();
[Bindable]
private var endTime:Date; [Bindable]
private var travelTypeList:ArrayCollection = new ArrayCollection( [
{ label: "步行", data: 0 },
{ label: "驾车", data: 1 },
{label: "自行车", data: 2 }]); [Bindable]
private var attributeParameters:Array = new Array({
"attributeName" : "Time",
"parameterName" : "TravelType",
"value" :1}); [Bindable]
private var impedanceAttributes:ArrayCollection = new ArrayCollection( [
{ label: "最短距离", data: "Distance" },
{ label: "最少时间", data: "Time" }]); [Bindable]
private var restrictionAttributes:Array=new Array("walking"); private const NL:String = "\n"; [Bindable]private var stopsFS:FeatureSet = new FeatureSet(); private var directionResult:directionResultGroup;
private var segmentGraphic:Graphic; private var tabImpactIndex:int = 0;
private function getDirections():void
{
//hanhh
/* directionResult =new directionResultGroup();
tabImpact.addChild(directionResult);
tabImpactIndex = tabImpact.numChildren-1;
tabImpact.selectedIndex = tabImpactIndex; */
//add by lizeping ,2014/02/13
startTime=startDateField.selectedDate;
startTime.hours=hoursStepper.value;
startTime.minutes=minutesStepper.value; stopsFS.features = [];
segmentGraphic = null;
//hanhh
// directionResult.map = map;
// map.defaultGraphicsLayer.clear();
var fromParameters:AddressToLocationsParameters = new AddressToLocationsParameters();
fromParameters.distance=0.005;
fromParameters.address = { SingleLine: fromTx.text, CountryCode: 'US' };
fromParameters.outFields = [ "Loc_name" ];
locator.addressToLocations(fromParameters, new AsyncResponder(
myResultFunction, myFaultFunction, "From")); var toParameters:AddressToLocationsParameters = new AddressToLocationsParameters();
toParameters.address = { SingleLine: toTx.text, CountryCode: 'US' };
toParameters.distance=0.005;
toParameters.outFields = [ "Loc_name" ];
locator.addressToLocations(toParameters, new AsyncResponder(
myResultFunction, myFaultFunction, "To")); function myResultFunction(result:Array, token:String = null):void
{
solveRoute(result, token);
}
function myFaultFunction(error:Fault, token:Object = null):void
{
Alert.show(error.faultString, "Locator Error");
}
} private function solveRoute(addressCandidates:Array, type:String):void
{
if (addressCandidates.length == 0)
{
Alert.show(type + " address not found.", "Missing Result");
return;
} var stop:AddressCandidate = addressCandidates[0]; if (type == "From")
{
map.defaultGraphicsLayer.remove(fromGraphic);
fromGraphic = new Graphic(stop.location, fromSymbol, { address: stop.address, score: stop.score });
map.defaultGraphicsLayer.add(fromGraphic);
stopsFS.features[0] = fromGraphic; }
else if (type == "To")
{
map.defaultGraphicsLayer.remove(toGraphic);
toGraphic = new Graphic(stop.location, toSymbol, { address: stop.address, score: stop.score });
map.defaultGraphicsLayer.add(toGraphic);
stopsFS.features[1] = toGraphic; } if (stopsFS.features[0] && stopsFS.features[1])
{
routeParams.attributeParameterValues=attributeParameters; routeTask.solve(routeParams);
}
} private function solveCompleteHandler(event:RouteEvent):void
{
directionResult =new directionResultGroup();
tabImpact.addChild(directionResult);
tabImpactIndex = tabImpact.numChildren-1;
tabImpact.selectedIndex = tabImpactIndex;
directionResult.map = map;
showStateResults();
var routeResult:RouteResult = event.routeSolveResult.routeResults[0];
directionResult.directionsFS = routeResult.directions;
//add at 2014-01-08 //var route:Graphic=routeResult.route;
directionResult.route=routeResult.route;
directionResult.graphicLayer.add(fromGraphic);//图标传给动态生成的tab页
directionResult.graphicLayer.add(toGraphic);//图标传给动态生成的tab页
map.defaultGraphicsLayer.clear();
directionResult.showResult();
} private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.faultString + "\n\n" + event.fault.faultDetail, "Routing Error " + event.fault.faultCode);
} private function formatDistance(dist:Number, units:String):String
{
var result:String = ""; var d:Number = Math.round(dist * 100) / 100; if (d != 0)
{
result = d + " " + units;
} return result;
} private function formatTime(time:Number):String
{
var result:String; var hr:Number = Math.floor(time / 60);
var min:Number = Math.round(time % 60); if (hr < 1 && min < 1)
{
result = "";
}
else if (hr < 1 && min < 2)
{
result = min + " 分钟";
}
else if (hr < 1)
{
result = min + " 分钟";
}
else
{
result = hr + " 小时 " + min + " 分钟";
} return result;
} protected function cmbTravelType_changeHandler(event:ListEvent):void
{
// TODO Auto-generated method stub
attributeParameters = new Array({
"attributeName" : "Time",
"parameterName" : "TravelType",
"value" : cmbTravelType.selectedItem.data});
if(cmbTravelType.selectedItem.data==0){
trace("use walking");
restrictionAttributes=new Array("walking");
}else{
restrictionAttributes=new Array("driving");
}
routeParams.attributeParameterValues=attributeParameters;
} protected function cmbImpedance_changeHandler(event:ListEvent):void
{
routeParams.impedanceAttribute=cmbImpedance.selectedItem.data; } protected function btnFrom_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
stopType="From";
myDrawTool.markerSymbol=fromSymbol;
myDrawTool.activate(DrawTool.MAPPOINT); } protected function btnTo_clickHandler(event:MouseEvent):void
{
// TODO Auto-generated method stub
stopType="To";
myDrawTool.markerSymbol=toSymbol;
myDrawTool.activate(DrawTool.MAPPOINT);
} protected function drawTool_drawEndHandler(event:DrawEvent):void
{
// reset after finished drawing a feature
myDrawTool.deactivate();
//查询地址信息
if(stopType=="From"){
map.defaultGraphicsLayer.remove(fromGraphic);
fromGraphic=event.graphic;
}else{
map.defaultGraphicsLayer.remove(toGraphic);
toGraphic=event.graphic;
}
var point:MapPoint=event.graphic.geometry as MapPoint;
locator.locationToAddress(point, 1000); } private function onLocationToAddressComplete(event:LocatorEvent):void
{ var candidate:AddressCandidate = event.addressCandidate; if (candidate && candidate.address && candidate.address.Address)
{
var address:Object = candidate.address; if(stopType=="From"){
fromTx.text=address.Address;
}
else{
toTx.text=address.Address;
}
}
else
{
Alert.show("This location does not have a known street address.");
}
} private function onFault(event:FaultEvent):void
{
if (event.fault.name == 'Error'
&& event.fault.faultCode == '500'
&& event.fault.faultString == 'An unexpected error occurred processing the request.')
{
Alert.show("Did you click too far from a road?\n\n" + event.fault.faultDetail, "No result");
}
else
{
Alert.show(event.fault.faultString + "\n\n" + event.fault.faultDetail, "Reverse Geocoding Error " + event.fault.faultCode);
}
} private function widgetClosedHandler(event:Event):void
{
map.defaultGraphicsLayer.clear();
} ]]>
</fx:Script> <fx:Declarations>
<!-- Symbol for all point shapes --> <esri:DrawTool id="myDrawTool" drawEnd="drawTool_drawEndHandler(event)"
graphicsLayer="{map.defaultGraphicsLayer}" map="{map}"/>
<!--http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer-->
<esri:Locator id="locator" fault="onFault(event)"
locationToAddressComplete="onLocationToAddressComplete(event)"
outSpatialReference="{map.spatialReference}" showBusyCursor="true"
url="{encodeURI(locatorURL)}"/> <esri:RouteTask id="routeTask" concurrency="last" fault="faultHandler(event)"
requestTimeout="30" showBusyCursor="true"
solveComplete="solveCompleteHandler(event)" url="{encodeURI(sUrl)}"/> <esri:RouteParameters id="routeParams" attributeParameterValues="{attributeParameters}"
directionsLengthUnits="esriMeters"
outputGeometryPrecisionUnits="esriDecimalDegrees"
outSpatialReference="{map.spatialReference}"
restrictionAttributes="{restrictionAttributes}"
returnDirections="true" returnRoutes="true" returnStops="true"
startTime="{startTime}" stops="{stopsFS}"/> <!--<esri:SimpleMarkerSymbol id="fromSymbol" color="0x00FF00"/>-->
<!--<esri:SimpleMarkerSymbol id="toSymbol" color="0xFF0000"/>-->
<esri:PictureMarkerSymbol id="fromSymbol" source="assets/skins/directions/green-A.png"/>
<esri:PictureMarkerSymbol id="toSymbol" source="assets/skins/directions/blue-B.png"/>
<esri:SimpleLineSymbol id="routeSymbol" width="4" alpha="0.5" color="0x0000FF"/>
<esri:SimpleLineSymbol id="segmentSymbol" width="8" alpha="0.5" color="0xFF0000"/>
<esri:SimpleLineSymbol id="tempSymbol" width="8" alpha="0" color="0xFF0000"/>
<s:DateTimeFormatter id="dtFormatter" dateTimePattern="MM/dd/yy, HH:mm"/>
</fx:Declarations>
<viewer:WidgetTemplate id="wTemplate" closed="widgetClosedHandler(event)" width="340" height="520"> <s:Group id="textInput" visible="false" width="100%" height="100%"
visible.textInput="true">
<s:Form width="100%">
<!-- 更改垂直间距 -->
<s:layout>
<s:FormLayout gap="-14"/>
</s:layout>
<s:FormItem label="起点:">
<s:HGroup width="100%">
<s:TextInput id="fromTx" text="{fromText}" width="90%"/>
<s:Image id="addFrom" buttonMode="true" click="btnFrom_clickHandler(event)" height="30"
source="@Embed('assets/skins/directions/add-stop.png')"
toolTip="{resourceManager.getString('ESRIMessages', 'directionsAddDestinationByMapClickTooltip')}"
useHandCursor="true"/>
</s:HGroup>
</s:FormItem>
<s:FormItem label="终点:">
<s:HGroup width="100%">
<s:TextInput id="toTx" text="{toText}" width="90%"/>
<s:Image id="addTo" buttonMode="true" click="btnTo_clickHandler(event)" height="30"
source="@Embed('assets/skins/directions/add-stop.png')"
toolTip="{resourceManager.getString('ESRIMessages', 'directionsAddDestinationByMapClickTooltip')}"
useHandCursor="true"/>
</s:HGroup>
</s:FormItem>
<s:FormItem label="出行方式:">
<mx:ComboBox id="cmbTravelType" change="cmbTravelType_changeHandler(event)"
dataProvider="{travelTypeList}" selectedIndex="1"/> </s:FormItem>
<s:FormItem label="路径选择:">
<mx:ComboBox id="cmbImpedance" change="cmbImpedance_changeHandler(event)"
dataProvider="{impedanceAttributes}" selectedIndex="0"/> </s:FormItem>
<s:FormItem label="出发时间:">
<s:HGroup><mx:DateField id="startDateField" formatString="YYYY-MM-DD" height="30"
selectedDate="{new Date()}">
</mx:DateField>
<s:NumericStepper id="hoursStepper" width="40" maximum="24" minimum="1">
</s:NumericStepper><s:Label text="时"/>
<s:NumericStepper id="minutesStepper" width="40" maximum="59" minimum="0"></s:NumericStepper><s:Label text="分"/>
</s:HGroup></s:FormItem>
<s:FormItem>
<s:Button label="查询" click="getDirections()" height="30"/>
</s:FormItem>
</s:Form>
</s:Group>
<s:Group id="resultsList" visible="false" width="100%" height="100%"
visible.resultsList="true">
<RichTabNavigator:RichTabNavigator id="tabImpact" width="100%" height="100%" backgroundAlpha="0"
cornerRadius="5" dropShadowVisible="false" horizontalAlign="left"
paddingTop="-1" tabHeight="30" tabWidth="110" borderVisible="true">
</RichTabNavigator:RichTabNavigator>
</s:Group> </viewer:WidgetTemplate>
</viewer:BaseWidget>
备注:
GIS技术交流QQ群:432512093
WebGIS二次开发培训入门群: 238339408