After you've completed the Getting Started, take a look at the tutorials listed below. These tutorials demonstrate how the MXML and ActionScript code is used to perform various functions in the ArcGIS API for Flex. Understanding each element of the code and its syntax will increase your productivity and save time.
All tutorials contain an overview and how-to guide.
- Using Map walks you through the creation of a map using MXML.
- Using Query shows you how to add a query task to a map.
- Using Extent demonstrates how to set extents, retrieve the current extent, and listen for extent changes.
- Using Graphic shows you how to take advantage of InfoSymbols and infoRenderers as well as define inline and external infoRenderers.
- Symbolizing Graphics shows you how to user renderers to easily assign symbols based on attributes of the graphics. [New in version 1.2]
- Geoprocessing tasks demonstrates the Geoprocessor class which allows you to access geoprocessing tasks on an ArcGIS Server.
- Routing tasks shows how to work with routing and driving directions using the RouteTask. [New in version 1.2]
- Styling Components shows you use modify your map compenents to give them your own style.
Using Map |
Tutorial overview
This tutorial shows you how to create an application with a map zoomed in to a specific location, illustrating how the ArcGIS API for Flex is used in an MXML page.
The following is the sample MXML code in its entirety:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:esri="http://www.esri.com/2008/ags" pageTitle="Tutorial - adding a map" > <esri:Map> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" /> <esri:extent> <esri:Extent xmin="-17.3" ymin="-34.6" xmax="51.1" ymax="38.2"/> </esri:extent> </esri:Map> </mx:Application>
View a sample.
Your code should always contain the same two parts:
- The namespace
- ActionScript code and/or MXML tags
How to create a map
- If desired, add a page title inside the <mx:Application> tag. This name will appear in your Web browser title bar.
- Add the map to your application by inserting the following code:
<esri:Map>
When you first use the esri namespace, Flex Builder automatically adds the namespace to the application tag. When you add <esri:Map>, Flex Builder automatically creates its matching end tag </esri:Map>.
- Add a layer from ArcGIS Online. For instance, add the following inside the Map tag:
<esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" />
The StreetMap service, a tiled MapService layer, is initialized using the ArcGISTiledMapServiceLayer constructor. The URL is the endpoint for this service. This endpoint is a reference to a service that you can find out using Services Directory.
- Set an extent. In this instance, you will add an extent with a specific bounding box to zoom in to Africa.
<esri:extent> <esri:Extent xmin="-17.3" ymin="-34.6" xmax="51.1" ymax="38.2"/> </esri:extent>
- Compile your complete application. You should see a map centered on Africa.
Using Query |
Working with Queries
NOTE: The following discussion assumes that you are familiar with the basic concepts of Flex.
Query Task
In this tutorial, you will learn how to use a query task to query information from an ArcGIS Server service. You will use Query, QueryTask, and FeatureSet to query a layer in a map and display the results. There are usually four steps involved in a query process:
- Setting up the Map and GraphicsLayer
- Setting up the query task with a query filter
- Executing the query task with user inputs, for example - by selecting features on a map, choosing a value from a list, or typing a value.
- Displaying the query results returned in a FeatureSet. The FeatureSet is comprised of both geometry and attributes of the selected features. The geometry can be used for highlighting the features on the map and attributes can be used to populate a DataGrid or a ToolTip.
The example below is a QueryTask where the user types in the name of a city. Based on this input, all cities that match the name are displayed on the map. Please refer to the end of this section for completed code.
Setting up the layers
The Map and its layers are used to provide a context to displaying the query results. The GraphicsLayer is used to symbolize and display the geometries of the query results. The code snippet below shows a map with an ArcGIS Server tiled map service layer and a graphics layer added to the map. The features that are rendered by the graphics layer will use the symbol defined by "infoSymbol1", that will be explained later.
<esri:Map id="map"> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/> <esri:GraphicsLayer id="myGraphicsLayer" symbol="{infoSymbol1}"/> </esri:Map>
It is not always necessary to have a map to perform a query. In situations where you just want to populate a DataGrid with the query results, a map is not needed (see sample).
Setting up the query task
The QueryTask sets up the URL of the layer that the query will work with. Note the URL includes the layer ID. In the code example below the layer ID is 0.
<esri:QueryTask id="queryTask" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0" />
The Query defines the criteria that will be used for executing the query. The actual filter is set by the "text" attribute (shorthand for a WHERE clause using LIKE operator) that is bound to the value of a text input component that we will see later. The field used is the display field defined in the map document. You can determine the display field for a layer in Services Directory. Since we want to display the results of our query we set the attribute "returnGeometry" to true.
In this example, a list of output fields is included in outFields. When you specify the output fields, you should limit the fields to only those you expect to use in the query or the results. The fewer fields you include, the faster the response will be. You must use the actual field names rather than the aliases (the aliases can be used in the results).
<esri:Query id="query" text="{qText.text}" returnGeometry="true"> <esri:outFields> <mx:String>CITY_NAME</mx:String> <mx:String>STATE_NAME</mx:String> </esri:outFields> </esri:Query>
Executing the query
In an application the query is executed based on inputs provided by the user. In the example below a panel is created with a text input for typing the name of the city to search and a button to execute the query. The click event of the button calls the doQuery() method, the first argument is the query criteria that we had previously defined and the second argument is an asynchronous responder. The responder sets the callback functions onResult() and onFault() that handles the success and failure of the query respectively.
<mx:Panel title="Search for a city" layout="horizontal" backgroundColor="0xB2BFC6" borderStyle="solid"> <mx:TextInput width="100%" id="qText" enter="doQuery()" text="San Jose"/> <mx:Button label="Do Query" click="doQuery()"/> </mx:Panel>
private function doQuery():void { queryTask.execute(query, new AsyncResponder(onResult, onFault)); }
Displaying query results
Displaying the results of the query involves adding the symbology to the graphic and adding the graphic itself to the graphics layer. The symbology can be applied directly to a graphics layer and all graphics added to that graphics layer will then inherit that symbology.
You may remember that when we added the graphics layer we set the symbol to "infoSymbol1". The code below shows the declaration of "infoSymbol1" which is a symbol of type InfoSymbol. The InfoSymbol has an infoRenderer that defines how information is rendered. In the example below, "data.CITY_NAME" and "data.STATE_NAME" are the outfields that we previously set in the query.
If the component that you use as the infoRenderer has in its inheritance chain a parent that implements IDataRenderer then all the attributes of the graphic are available via the "data" property. In the example below the component "VBox" has a parent "Container" that implements the IDataRenderer. For more information refer to the Adobe Flex 3 Language reference.
<esri:InfoSymbol id="infoSymbol1"> <esri:infoRenderer> <mx:Component> <mx:VBox> <mx:Label text="{data.CITY_NAME}"/> <mx:Label text="{data.STATE_NAME }"/> </mx:VBox> </mx:Component> </esri:infoRenderer> </esri:InfoSymbol>
After the successful execution of the query the callback function onResult() is called. One of the arguments to the function is a FeatureSet object that contains the results of the query. The features of the FeatureSet can be directly assigned to the graphicProvider of the graphics layer to be rendered on the map.
In case of a failure the callback function onFault() is called which in the example below show an alert box with information about the failure.
private function doQuery():void { queryTask.execute(query, new AsyncResponder(onResult, onFault)); function onResult(featureSet:FeatureSet, token:Object = null ):void { myGraphicsLayer.graphicProvider = featureSet.features; } function onFault(info:Object, token:Object = null):void { Alert.show( info.toString() ); } }
The complete code for the scenario discussed in this section is below,
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:esri="http://www.esri.com/2008/ags" pageTitle="Query Task" > <mx:Script> <![CDATA[ import com.esri.ags.Graphic; import com.esri.ags.tasks.FeatureSet; import mx.controls.Alert; import mx.rpc.AsyncResponder; private function doQuery():void { queryTask.execute(query, new AsyncResponder( onResult, onFault)); function onResult(featureSet:FeatureSet, token:Object = null):void { myGraphicsLayer.graphicProvider = featureSet.features; } function onFault(info:Object, token:Object = null):void { Alert.show(info.toString()); } } ]]> </mx:Script> <!-- Layer with US States --> <esri:QueryTask id="queryTask" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0" /> <esri:Query id="query" text="{qText.text}" returnGeometry="true"> <esri:outFields> <mx:String>CITY_NAME</mx:String> <mx:String>STATE_NAME</mx:String> </esri:outFields> </esri:Query> <esri:InfoSymbol id="infoSymbol1"> <esri:infoRenderer> <mx:Component> <mx:VBox> <mx:Label text="{data.CITY_NAME }"/> <mx:Label text="{data.STATE_NAME }"/> </mx:VBox> </mx:Component> </esri:infoRenderer> </esri:InfoSymbol> <mx:Panel title="Search for a city" layout="horizontal" backgroundColor="0xB2BFC6" borderStyle="solid"> <mx:TextInput width="100%" id="qText" enter="doQuery()" text="San Jose"/> <mx:Button label="Do Query" click="doQuery()"/> </mx:Panel> <esri:Map id="map"> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/> <esri:GraphicsLayer id="myGraphicsLayer" symbol="{infoSymbol1}"/> </esri:Map> </mx:Application>
Performance considerations
There is a direct correlation between performance and the number of features selected; certain queries are unrealistic or request too much data. The list below offers suggestions to enhance performance.
- If a large number of features is selected, it can take some time to draw the graphics on the map. The type of feature also makes a difference. Points draw much faster than lines and polygons. Therefore, use point graphics (MapPoint or MultiPoint) whenever possible.
- If you are retrieving tabular data and do not intend to add graphics to the map, you should not request geometry.
- If queries are too large on a regular basis, limit the query to a smaller area or refine the query so fewer features are returned at one time.
- To prevent queries that request unlimited numbers of features (e.g., empty WHERE statements and statements that are always true), use MaxRecordCount to set the maximum number of features. By default, the maximum for ArcGIS Server is 500 features. You can modify this for a specific MapService in its configuration file. For a default windows installation, the file is C:\Program Files\ArcGIS\server\user\cfg\[YourMapService].cfg
- Queries on cached layers do not have scale dependencies. This means that features for a layer can be queried even if the layer is not displayed on the map for a given scale. Thus, your query should not be accessible for a layer if displaying the results does not make sense to the end user.
Using Extent |
Tutorial overview
NOTE: The following discussion assumes that you are familiar with the basic concepts of Flex.
This tutorial describes several ways to set a map's extent as well as how to retrieve the extent for use in other operations.
If you do not include extent information when you initialize a map, the default extent is used, which is the extent of the map as it was last saved in the map document. If you use multiple layers, or services, the default extent is the initial extent of the basemap or first layer added.
How to set an extent
To set an initial extent that is different from the default extent, use the extent property or Extent class.
- Set the map extent using the extent property.
- Add your map.
- Insert the <esri:Extent> tag and specify the ID and coordinates.
- Add the <esri:ArcGISDynamicMapServiceLayer> tag.
Your code should look similar to below.
<esri:SpatialReference id="wgs" wkid="4326"/> <esri:Extent id="extentOfKansas" xmin="-103" ymin="36" xmax="-94" ymax="41" spatialReference="{wgs}"/> <esri:Map id="myMap" extent="{extentOfKansas}"> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/> <esri:ArcGISDynamicMapServiceLayer id="myLayer" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Petroleum/KGS_OilGasFields_Kansas/MapServer" /> </esri:Map>
View another sample map extent set using the extent property.
- Set the initial map extent using the Extent class.
- Add your map.
- Add the <esri:SpatialReference> tag and specify the desired projection and well-known ID.
- Insert the <esri:extent> tag and specify the ID and coordinates.
- Add the <ArcGISTiledMapServiceLayer> tag.
Your code should look similar to below.
<esri:SpatialReference id="wgs" wkid="4326"/> <esri:Map id="myMap"> <esri:extent> <esri:Extent xmin="-103" ymin="36" xmax="-94" ymax="41" spatialReference="{wgs}"/> </esri:extent> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/> <esri:ArcGISDynamicMapServiceLayer id="myLayer" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Petroleum/KGS_OilGasFields_Kansas/MapServer" /> </esri:Map>
View another sample map extent set using the Extent class.
How to set an extent when using multiple services
In some cases, you may want to use the extent of a layer that is not the initial layer or basemap. To do this, set the map extent to the extent of the desired layer.
In the following example, two layers are used: the base layer—ArcGIS Online world extent—and a second layer—the state of Kansas.
To set Kansas as the extent, add a load property that sets the extent of the map.
load="{myMap.extent=myKansasLayer.fullExtent}"
The load property creates the map and, when loaded, sets the full extent to the Kansas layer.
The code below sets the map extent to myKansasLayer using fullExtent.
<esri:Map id="myMap"> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/> <esri:ArcGISDynamicMapServiceLayer load="{myMap.extent=myKansasLayer.fullExtent}" id="myKansasLayer" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Petroleum/KGS_OilGasFields_Kansas/MapServer" /> </esri:Map>
NOTE: If you want to set the initial extent instead of the full extent, use myKansasLayer.initialExtent.
How to get the current extent
Retrieve the current map extent using the extent property.
How to listen to extent changes
The map will fire off an ExtentEvent every time the user pan or zooms the map. You can add an event listener using either mxml or ActionScript to be notified of extent changes. See for example the Event sample
<esri:Map id="myMap" extentChange="displayExtent()"> <esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" /> </esri:Map>
myMap.addEventListener(ExtentEvent.EXTENT_CHANGE, extentChangeHandler);
Using Graphic |
Tutorial overview
NOTE: The following discussion assumes that you are familiar with the basic concepts of Flex.
Working with Graphics
The GraphicsLayer enables overlaying graphics on top of the map. The graphics can be drawn by the user as markup or input to a task, or they can be drawn by the application in response to a task. For example, the application might add the results of a query to the map as graphics.
- A graphic is comprised of:
- Geometry - The geometry determines where the graphic is located and can be point, multipoint, polyline, polygon or extent.
- Symbol - The symbol determines how the graphic looks and can be a marker symbol (for point and multipoint geometries), a line symbol (for polylines), or a fill symbol (for polygons).
- Attributes - These are name-value pairs that describe the graphic. If you create the graphic, you need to assign the attributes. If the graphic is created in response to a task performed on a layer, the graphic automatically includes the field attributes of the layer. Some tasks allow you to limit the attributes that are returned to the result graphic. Query.outFields is an example of a property that limits the returned attributes of a task.
Graphics are not required to have all of the above items, and no one item is required. For example, many task results are returned as graphic objects in a FeatureSet. These graphics only have geometry and attributes when they are returned. If you want to add the graphics to a map, you must define a symbol for them.
If you're writing code that allows users to draw graphics on the map, the Draw toolbar can make your work easier. The Draw toolbar is a class that can help you capture the geometry that a user draws on the screen. You can then define a symbol and apply it to the geometry in a new graphic object. The drawing toolbar sample demonstrates this workflow.
The way that you add task results to the map as graphics varies by task type. If your task returns a FeatureSet, you get an array of graphics (FeatureSet.features) that you can assign to the graphicProvider of the GraphicsLayer. The code below shows how you might do this with results from QueryTask. Note that the code defines a symbol to the GraphicLayer that is assigned to all the graphics added to that layer.
private function doQuery():void { queryTask.execute(query, new AsyncResponder(onResult, onFault)); function onResult(featureSet:FeatureSet, token:Object = null):void { myGraphicsLayer.graphicProvider = featureSet.features; } function onFault(info:Object, token:Object = null):void { Alert.show( info.toString() ); } }
<esri:SimpleMarkerSymbol id="sms" size="10" color="0xFF0000" style="circle" /> <esri:GraphicsLayer id="myGraphicsLayer" symbol="{sms}"/>
Other tasks do not provide a feature set as a result but do provide the geometry, which you can use to create a graphic. For example, a Locator task finds an AddressCandidate, whose location property is a MapPoint geometry. You can use this geometry to create a graphic showing the address location, as in the code below:
for each (var candidate:AddressCandidate in candidates) { if (candidate.score > 80) { var myGraphic:Graphic = new Graphic(); myGraphic.geometry = candidate.location; myGraphic.symbol = mySymbol; myGraphic.attributes = { address: candidate.address,score: candidate.score, locatorName: candidate.attributes.Loc_name }; myGraphicsLayer.add(myGraphic); } }
See the Samples for more ideas of how to create graphics from the results of different tasks.
Working with Symbols
Symbols that are available to render the graphic are SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, PictureMarkerSymbol, PictureFillSymbol, InfoSymbol, CartographicLineSymbol and CompositeSymbol. Refer to the samples to learn how to use the different symbols.
Infosymbol and infoRenderer
InfoSymbols are small windows containing user interface (UI) controls and data that provide information about a point feature on a map. Unlike InfoWindows, multiple InfoSymbols can be displayed on a map at one time.
InfoSymbol has two properties infoPlacement and infoRenderer. The property infoPlacement determines the orientation of the symbol. Refer to the InfoPlacement class for the list of possible values.
The property infoRenderer is of type IFactory and can be defined as either inline or external. The infoRenderer contains the definition of UI controls to add to the InfoSymbol and the data that determines its appearance. Once the InfoSymbol has been created, it can be assigned as a graphic symbol, similar to a MarkerSymbol.
Defining inline infoRenderer
You can define infoRenderers as inline, i.e. defined in the same file as InfoSymbol.
- To define an inline infoRenderer:
- Insert InfoSymbol and infoRenderer tags.
- Define UI controls within the <mx:Component> tag. These will be the contents of InfoSymbol.
- If necessary, use outerDocument to include variables and methods outside <mx:Component>.
<esri:InfoSymbol id="infoSymbol1"> <esri:infoRenderer> <mx:Component> <mx:VBox> <mx:Panel id="myPanel" height="100%" width="100%" backgroundAlpha="0" initialize="{outerDocument.initPanel(event)}"/> <mx:Button id="myButton" height="100%" width="100%" backgroundAlpha="0" click="{outerDocument.showResults()}"/> </mx:VBox> </mx:Component> </esri:infoRenderer> </esri:InfoSymbol>
Defining external infoRenderer
Defined in a separate file from InfoSymbol, external infoRenderers are preferred because of their modular, reusable design. The external infoRenderer is defined by taking all the content that would be contained between the <mx:Component> tags and placing it in a discrete MXML or ActionScript file. An example of an infoRenderer in a separate MXML file called MyInfoRenderer.mxml will look like below.
<?xml version="1.0" encoding="utf-8"?> <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" label="{data.STATE_NAME}" backgroundColor="0xEEEEEE"> <mx:Label text="State Fips: {data.STATE_FIPS}"/> <mx:Label text="Abbreviation: {data.STATE_ABBR}"/> <mx:Label text="Area: {data.AREA}"/> </mx:VBox>
Once defined, the infoRenderer can be used by any InfoSymbol in ActionScript or MXML.To set the infoRenderer in ActionScript, construct your code similar to the following:
var mySymbol:InfoSymbol = new InfoSymbol(); mySymbol.infoRenderer = new ClassFactory(MyInfoRenderer); myGraphic.symbol = mySymbol;
To set the infoRenderer in MXML, construct your code similar to the following:
<esri:InfoSymbol id="infoSymbol1" infoRenderer="MyInfoRenderer"/>
Limitations
InfoSymbol can only be assigned to points. To add InfoSymbols to multipoints, convert them to points. To add InfoSymbols to lines or polygons, you can find a label point of the line or polygon and either change the graphic's geometry to centerpoint or create a new point graphic at the location of the centerpoint.
For example:
var polygon: Polygon; var centerPt: MapPoint; polygon = myGraphic.geometry as Polygon; centerPt = polygon.extent.center; myGraphic.geometry = centerPt;
Symbolizing graphics with renderers |
Graphics are symbolized with "symbols". Symbols can be assigned to graphics in several different ways.
- a symbol on the graphic,
- a symbol on the graphics layer (works as the default for graphics that don't have a particular symbol or renderer),
- a renderer (new in version 1.2 of the ArcGIS API for Flex):
- SimpleRenderer
- ClassBreaksRenderer with optional default symbol
- UniqueValueRenderer with optional default symbol
Note that while you can have different geometries (for example points and lines in the same graphics layer), renderers works best when the layer only have one type of geometry.
A renderer defines a set of symbols that will be used for graphics in a graphics layer. You can use renderers to symbolize features with different colors or sizes based on a particular attribute. Here is a basic MXML example from our live samples:
<esri:SimpleMarkerSymbol id="smallSym" size="6" color="0xFF0000" alpha="0.7"/> <esri:SimpleMarkerSymbol id="mediumSym" size="10" color="0xFF0000" alpha="0.7"/> <esri:SimpleMarkerSymbol id="largeSym" size="16" color="0xFF0000" alpha="0.7"/> ... <esri:GraphicsLayer id="graphicsLayer"> <esri:renderer> <esri:ClassBreaksRenderer attribute="ranking"> <esri:ClassBreakInfo maxValue="0.33" symbol="{smallSym}"/> <esri:ClassBreakInfo minValue="0.33" maxValue="0.67" symbol="{mediumSym}"/> <esri:ClassBreakInfo minValue="0.67" symbol="{largeSym}"/> </esri:ClassBreaksRenderer> </esri:renderer> </esri:GraphicsLayer>
There are three renderers in the ArcGIS API for Flex: simple renderer, class breaks renderer, and unique value renderer. Corresponding classes are found in esri.renderer as SimpleRenderer, ClassBreaksRenderer, and UniqueValueRenderer respectively.
Simple renderer
A simple renderer uses the same symbol for every graphic. All you have to do is specify the symbol to be used by the renderer, then apply the renderer to the graphics layer. This is equivalent to setting the symbol on the graphics layer.
<esri:GraphicsLayer id="graphicsLayer"> <esri:renderer> <esri:SimpleRenderer symbol="{smallSym}"/> </esri:renderer> </esri:GraphicsLayer>
or
<esri:GraphicsLayer id="graphicsLayer" symbol="{smallSym}"/>
Class breaks renderer
A class breaks renderer symbolizes each graphic based on the value of one of its attributes. Graphics with attribute values inside the class break (a.k.a. "range") will all use the same symbol. The "breaks" define the values at which the symbology changes.
For example, suppose you have a "buildings" layer with an attribute that defines the building age. You want to symbolize buildings constructed since the year 2000 in green, buildings constructed between 1980 and 2000 in yellow, and buildings built before 1980 with red. This would be a good scenario for a class breaks renderer.
To use a class breaks renderer, you simply add one or more breaks. Each break specifies the symbol to use and the minimum and maximum values that will be used for that symbol. The example below shows how you can explicitly define breaks:
var smallSym:SimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,6, 0xFF0000, 0.7); var mediumSym:SimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,10, 0xFF0000, 0.7); var largeSym:SimpleMarkerSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE,16, 0xFF0000, 0.7); var classBreaksRenderer:ClassBreaksRenderer = new ClassBreaksRenderer(); classBreaksRenderer.attribute = "BUILD_DATE"; var classBreakInfos:Array = [ new ClassBreakInfo(smallSym, Number.NEGATIVE_INFINITY, 1980), new ClassBreakInfo(mediumSym, 1980, 2000), new ClassBreakInfo(largeSym, 2000, Number.POSITIVE_INFINITY) ]; classBreaksRenderer.infos = classBreakInfos; graphicsLayer.renderer = classBreaksRenderer;
Note that if there is no maximum limit on a break, you can use "Number.POSITIVE_INFINITY" for the maximum value. Similarly, you can use "Number.NEGATIVE_INFINITY" when there is no minimum.
Any value that is greater than or equal to the minimum will be included in the break. Any value that is less than the maximum will be included in the break. Thus, if you have two breaks 0 - 10 and 10 - 20, the value 10 would fall in the second break (10 - 20). Avoid creating overlapping breaks or gaps between breaks.
You can also define breaks mathematically. For example, you can do some basic arithmetic to ensure that each break falls an equal distance apart given the input data (sometimes known as an "equal interval" classification):
var numRanges : int = 10; var breaks:Number = (max - min) / numRanges; for (var i:int = 0; i < numRanges; i++) { classBreakInfos.push(new ClassBreakInfo( new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, (i+1)*5, 0xFF0000, 0.7), min + (i*breaks), min + ((i+1)*breaks) ) ); }
Unique value renderer
A unique value renderer symbolizes groups of graphics that have matching attributes. For example, you could use a unique value renderer to symbolize zoning designations: red for "Residential", green for "Industrial", blue for "Commercial", and so on.
To define a unique value renderer you specify the attribute on which to base it on, and an optional defaultSymbol for values that are not covered by a specific UniqueValueInfo. Each "UniqueValueInfo" contains the specific value and symbol to use for each "unique value".
<esri:SimpleFillSymbol id="rFill" alpha="0.5" color="0xFF0000"/> <esri:SimpleFillSymbol id="gFill" alpha="0.5" color="0x00FF00"/> <esri:SimpleFillSymbol id="bFill" alpha="0.5" color="0x0000FF"/> <esri:UniqueValueRenderer id="uniqueValueRenderer" attribute="ZONING"> <esri:UniqueValueInfo value="Residential" symbol="{rFill}"/> <esri:UniqueValueInfo value="Industrial" symbol="{gFill}"/> <esri:UniqueValueInfo value="Commercial" symbol="{bFill}"/> </esri:UniqueValueRenderer>
The equivalent code with ActionScript:
var rFill:SimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, 0xFF0000, 0.5); var gFill:SimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, 0x00FF00, 0.5); var bFill:SimpleFillSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, 0x0000FF, 0.5); var uniqueValuerenderer:UniqueValueRenderer = new UniqueValueRenderer(); uniqueValuerenderer.attribute = "ZONING"; var uniqueValueInfos:Array =[]; uniqueValueInfos.push(new UniqueValueInfo(rFill, "Residential")); uniqueValueInfos.push(new UniqueValueInfo(gFill, "Industrial")); uniqueValueInfos.push(new UniqueValueInfo(bFill, "Commercial")); uniqueValuerenderer.infos = uniqueValueInfos; graphicsLayer.renderer = uniqueValuerenderer;
Values that you don't add to the list are not drawn - unless you specify a defaultSymbol on the UniqueValueRenderer, in which case those graphics will be drawn with the default symbol.
Live renderer samples
- Using renderers - using ClassBreaksRenderer.
- Drive Times - using UniqueValueRenderer.
Geoprocessing tasks |
Geoprocessing allows you to automate your GIS analyses by creating custom tools and linking them within ArcGIS. You can arrange these tools in a logical way to accomplish a multistep task in a single operation rather than a series of manually run tools.
The Geoprocessor class in the ArcGIS API for Flex gives you access to various geoprocessing tasks, which are exposed through services in the ArcGIS Server Services Directory.
To use the geoprocessing services, obtain the following information from the Services Directory:
- The URL of the geoprocessing task
- The required inputs and outputs of the task
- The task type synchronous or asynchronous
Obtaining the URL
The Services Directory links to all available services. The image below shows a sample geoprocessing service:
From this page, you can see that the geoprocessing service ESRI_Elevation_World is located in the Elevation folder and runs on sampleserver1.arcgisonline.com.
The following appears when you click the Viewshed geoprocessing model:
To execute this geoprocessing task, copy and paste this MXML code into your application:
<esri:Geoprocessor id="gp" url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed" />
The equivalent code with ActionScript:
var gp:Geoprocessor = new Geoprocessor("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed");
Supplying the parameters
The parameters in the Services Directory show the required inputs and outputs of the task. In the example above, you need to supply all parameters whose Direction is esriGPParameterDirectionInput and whose Parameter Type is esriGPParameterTypeRequired.
You do not have to supply the output parameters because the output is always returned as an array of ParameterValue.
For instance, the input parameters might look like:
var params:Object = "Input_Observation_Point":featureSet, "Viewshed_Distance":vsDistance );
Running the task
The way you run the task depends on whether the geoprocessing task is synchronous or asynchronous.
In the case of synchronous execution, the client executes the task and waits for a response before proceeding. The Supported Operations section of the Services Directory displays "Execute Task" for synchronous tasks.
In an asynchronous execution, the client submits a job, then verifies that it was successful using a unique job ID. When the task completes, the client can retrieve the results. The Supported Operations section of the Services Directory displays "Submit Job" for asynchronous tasks.
To run a synchronous task, call Geoprocessor.execute(). Supply the input parameters for the task and optionally include a callback function that tells the application how to handle the results.
gp.execute(params, myFunction);
The results of the task are returned to the callback function as an array of ParameterValue. If messages are enabled, you also get an array of GPMessage objects.
You can loop through each item in the results array and add it to the map. For instance:
private function displayResult(event:GeoprocessorEvent):void { for each ( var myGraphic:Graphic in event.parameterValues[0].value.features ) { myGraphic.symbol = viewshedSimpleFill; myGraphicsLayer.add( myGraphic ); } }
where viewshedSimpleFill has been defined in MXML as:
<esri:SimpleFillSymbol id="viewshedSimpleFill" color="0xFF0000" alpha="0.5"> <esri:SimpleLineSymbol color="0x000000" width="1"/> </esri:SimpleFillSymbol>
To run an asynchronous task, call Geoprocessor.submitJob(). Supply the input parameters and optionally specify (1) a complete callback function to be called when the job is successful and (2) a status callback function when the geoprocessor checks the job status.
gp.submitJob(params, MyCompleteCallback, myStatusCallback);
The status callback receives a JobInfo object containing the job ID, the job status, and any GPMessage objects returned by the geoprocessor.
Routing tasks |
Working with the RouteTask
When you work with the RouteTask, you'll follow the general pattern of:
- creating the task,
- configuring the parameters,
- solving the route, and
- displaying the result.
1. Creating the route task
When you create an instance of RouteTask, you provide a URL that is the REST endpoint to an ArcGIS Server network analysis service. You can copy and paste this MXML code into your application:
<esri:RouteTask id="routeTask" url="http://tasks.arcgisonline.com/ArcGIS/rest/services/NetworkAnalysis/ESRI_Route_NA/NAServer/Route" />
The equivalent code with ActionScript:
var routeTask:RouteTask = new RouteTask ("http://tasks.arcgisonline.com/ArcGIS/rest/services/NetworkAnalysis/ESRI_Route_NA/NAServer/Route");
2. Configuring the route parameters
In order to get the results you want from the route task, you need to specify the details of your routing problem such as stop locations, barrier locations, the impedance attribute, etc. You do this using RouteParameters. The example below shows how you'd use RouteParameters to define two stops for a route using ActionScript only. See the Route samples for a mix of MXML and ActionScript.
var routeParams:RouteParameters = new RouteParameters(); var stop1:Graphic = new Graphic(new MapPoint(-117.21,34.065); var stop2:Graphic = new Graphic(new MapPoint(-117.185,34.05); var stops:FeatureSet = new FeatureSet([ stop1, stop2]); routeParams.stops = stops;
For a complete description of each route parameter, see the RouteParameters entry in the API reference.
3. Solving the route
Once you've created the route task and configured its parameters, you can call RouteTask.solve() to solve the route.
routeTask.solve(routeParams);
In addition to calling the solve method, you need to handle the solveComplete and fault events on the RouteTask. These functions define what the application will do with the results, whether the result is a route or an error message.
<esri:RouteParameters id="routeParams" solveComplete="solveCompleteHandler(event)" fault="faultHandler(event)" />
The equivalent code with ActionScript:
routeTask.addEventListener(RouteEvent.SOLVE_COMPLETE, solveCompleteHandler); routeTask.addEventListener(FaultEvent.FAULT, faultHandler);
Either way, you would usually create the actual functions as:
private function solveCompleteHandler(event:RouteEvent):void { var routeResult:RouteResult = event.routeSolveResult.routeResults[0]; ... } private function faultHandler(event:FaultEvent):void { Alert.show(event.fault.faultString, "Routing Error"); }
Optimizing the route(s)
The RouteTask can help you find the most efficient path for visiting a given list of stops. This is sometimes known as the traveling salesperson problem. To solve it, set RouteParameters.findBestSequence to true and the stops will be visited in the most efficient order. You can optionally designate whether the first and last stops on the list should remain fixed or not.
routeParams.findBestSequence = true; //routeParams.preserveFirstStop = true; //routeParams.preserveLastStop = true;
Turn-by-turn directions
The RouteTask can return turn-by-turn driving directions between stops. To get the directions, set RouteParameters.returnDirections to true.
routeParams.returnDirections = true;
Advanced options
Batch routing, i.e. solving multiple routes in one request is also possible. Stops with same name will be grouped into sets for solving individual routes. For the batch routing result, you'll get an array of RouteResults containing each route.
Constrain stop visits to certain times of day, or time windows - for in-depth information on how time windows work, see Routing with time windows in the ArcGIS Desktop Help.
Live route samples
- Routing - basic routing example.
- Route Barriers - using barriers to avoid certain locations.
- Route Directions - showing turn-by-turn driving directions.
Styling Components |
The API along with its classes has UI components that can be customized to suit your application needs.
Styles are the visual properties of components such as size, color, etc. A style can be applied to all instances of a component using a Type Selector style or just individual instances using a Class Selector style. In Flex the style definition is declared within the <mx:Style> tag. The style properties that are available for modification for a component can be found in the API reference. The components that can be styled are found under the package com.esri.controls.
On this page we will show how to style three different components:
Styling the Navigation toolbar
Navigation — The navigation control is used to display layers at predefined scales. The default navigation control is as shown in Figure 1. It consists of a VSlider and a plus and minus button. The default look of the navigation control (Figure 1) can be changed to suit your project. The section below shows how to style the navigation control as shown in Figure 2. See the Styling zoom slider with CSS sample.
Figure 1 - default navigation control. | Figure 2 - styled navigation control. |
The class com.esri.ags.controls.Navigation represents the Navigation control. The control supports a set of style classes that can be used to provide a different appearance to the slider. The style classes used by the navigation control are,
- Navigation – this class controls the location of the slider and enables placing the slider to the left or right side of the Map.
The style below will place the slider at a distance of 30 pixels from the top and right margin of the Map. Since the property left is a default property you will have to use the value NaN so that the value of property left is not used.
Navigation { top: 30; right: 30; left: NaN; }
- NavigationMinusButton – this class controls the appearance of the Zoom Out button placed at the bottom of the slider. This class inherits mx.controls.Button and hence all the style properties that can be applied on mx.controls.Button can be used.
The style below sets the different states of the NavigationMinusButton. These properties are standard style properties of a Button. In this case the button is assigned an image of a globe.
NavigationMinusButton { disabledSkin: Embed(source="assets/globe_icon.png"); downSkin: Embed(source="assets/globe_icon.png"); overSkin: Embed(source="assets/globe_icon.png"); upSkin: Embed(source="assets/globe_icon.png"); }
- NavigationPlusButton – this class controls the appearance of the Zoom In button placed at the top of the slider. This class inherits mx.controls.Button and hence all the style properties that can be applied on mx.controls.Button can be used.
The style below sets the different states of the NavigationPlusButton. These properties are standard style properties of a Button. In this case the button is assigned an image of a home.
NavigationPlusButton { disabledSkin: Embed(source="assets/home_icon.png"); downSkin: Embed(source="assets/home_icon.png"); overSkin: Embed(source="assets/home_icon.png"); upSkin: Embed(source="assets/home_icon.png"); }
- NavigationSlider – this class controls the appearance of the slider. The NavigationSlider inherits mx.controls.VSlider and hence all the style properties that can be applied on an mx.controls.VSlider can also be applied on a NavigationSlider.
The style below defines the appearance of the slider. Except for the property show-scale-in-data-tip all other properties are inherited from a VSlider.
NavigationSlider { show-scale-in-data-tip:false; /*display tile level instead of scale */ dataTipPlacement: "left"; show-track-highlight: true; tick-color: #ffffff; } ToolTip { backgroundAlpha: 1.0; backgroundColor: haloBlue; fontWeight: bold; color: white; }
Styling the InfoSymbol
InfoSymbol – These are callouts that are used to display content, usually the results of a query. InfoSymbols can only be used with a graphic of type MapPoint. The class InfoSymbolContainer represents style that is used to render the InfoSymbol.
The callout in figure 3 is displayed with the default style. To change the style use a CSS class called InfoSymbolContainer and set the appropriate values. The InfoSymbolContainer inherits mx.core.container hence all the style properties that can be applied on an mx.controls.container can be used.
Figure 3 - default InfoSymbol. | Figure 4 - styled InfoSymbol. |
The style below represents the style as it is displayed in Figure 4,
InfoSymbolContainer { backgroundColor: #FF530D; backgroundAlpha: 1.0; font-style: italic; font-weight: bold; font-size: 12; }
Adding behaviors to infosymbols – In addition to adding styling properties, behaviors can also be added to the infoSymbols. The figures below show an example of a infoSymbol with a user-defined behavior. The Figures 6 and 7 show the mouse hover and mouse click behavior of the infoSymbol. This example takes advantage of the States feature of the Flex framework to assign behavior. See the InfoSymbol with States sample for more information on how this behavior is implemented.
Figure 5 - default state of InfoSymbol with user-defined behavior. | Figure 6 - hover (or mouse over) state of InfoSymbol with user-defined behavior. | Figure 7 - state of InfoSymbol with user-defined behavior after click. |
Styling the ScaleBar
ScaleBar – the scalebar supports two styling properties. They are fillColor and outlineColor. The default ScaleBar style is shown in Figure 8. The scale bar shown in Figure 9 uses the style properties below.
ScaleBar { fillColor: #FF530D; outlineColor: #FFFFFF; }
Figure 8 - default scale bar. | Figure 9 - styled scale bar. |