The ArcGIS JavaScript API allows for the drawing of graphics on top of the map. Graphics can be drawn by a user as markup or input to a task, or they can be drawn by an application in response to a task. For example, an application might add the results of a query to the map as graphics.
You can create and add one or more layers for graphics to your ArcGIS JavaScript API maps. A GraphicsLayer contains an array of Graphic objects. The array is empty initially, but you can add graphics any time after the map loads.
Think of a graphic as a container for four things: A geometry, a symbol, attributes and an info template.
All four properties: geometry, symbol, attributes and info template, are optional. 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 and set a symbol for them.
If you're writing code that allows users to draw graphics on the map, the Draw toolbar makes this easy. 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 tools 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 loop through and add to the map. The code below shows how you might do this with results from QueryTask. Notice that the code defines a symbol and an info template for the graphic.
queryTask.on("complete", function(featureSet) { map.graphics.clear(); var symbol = new SimpleFillSymbol(); // Loop through features in the featureSet and add them to the map. for (var i=0, il=featureSet.features.length; i<il; i++) { // Get the current feature from the featureSet. // Feature is a graphic var graphic = featureSet.features[i]; graphic.setSymbol(symbol); graphic.setInfoTemplate(infoTemplate); //Add graphic to the map graphics layer. map.graphics.add(graphic); } });
Other tasks do not provide a feature set as a result but do provide the geometry, which you can use to create a graphic. A Locator returns one or more AddressCandidates, which have a location property that is a Point. You can use this geometry to create a graphic showing the address location, as in the code below:
for (var i=0, il=candidates.length; i<il; i++) { candidate = candidates[i]; if (candidate.score > 80) { var attributes = { address: candidate.address, score: candidate.score, locatorName: candidate.attributes.Loc_name }; var graphic = new Graphic(candidate.location, symbol, attributes, infoTemplate); map.graphics.add(graphic); } }
See the Samples for more ideas of how to create graphics from the results of different tasks.
Below are some ways that you can optimize your code when working with graphics and their associated geometries and symbols.
Adding graphics to the map
When adding a graphic to map, always set the geometry and symbology of the graphic before adding it to the map's graphics layer. If a graphic has been added to a map, calling setGeometry or setSymbol will force the graphic to redraw.
Less efficient:
var graphic = new Graphic(geometry, defaultSymbol); map.graphics.add(graphic); if (isSelected) { graphic.setSymbol(highlightSymbol); }
More efficient:
var graphic = new Graphic(geometry, isSelected ? highlightSymbol : defaultSymbol); map.graphics.add(graphic);
Creating and customizing symbols
When you create a symbol, you should use the default symbol constructor and override just the custom properties. Check the default set of properties of each symbol type before you start customizing the symbol.
The code below creates a symbol by setting all properties, even though the default symbol is already a solid line. This is less efficient:
var symbol = new SimpleLineSymbol( SimpleLineSymbol.STYLE_SOLID, new Color([255,0,0]), 1) );
The code below is more efficient. It takes the default symbol and only overrides properties that need to be customized, in this case, the color:
var symbol = new SimpleLineSymbol().setColor(new Color([255,0,0]));
Note that you can only use this technique with symbols that have a default constructor. These are CartographicLineSymbol, SimpleFillSymbol, SimpleLineSymbol and SimpleMarkerSymbol.
Chaining methods
Chaining method calls can reduce the lines of code you write. Instances of Graphic and the various symbols classes, such as SimpleMarkerSymbol, provide setter methods that return the object itself, allowing for chaining of methods.
Less efficient:
var symbol = new SimpleMarkerSymbol(); symbol.setSize(10); symbol.setColor(new Color([255,0,0]));
More efficient:
var symbol = new SimpleMarkerSymbol().setSize(10).setColor(new Color([255,0,0]));
When chaining method calls, you need to determine a balance between efficiency and readability of your code. Your code might be more readable and maintainable if you avoid chaining; however, you will forfeit the performance benefit that chaining offers.