Hide Table of Contents
Working with graphics

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.

  • The geometry determines where the graphic is located and can be point, multipoint, polyline, or polygon.
  • 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.
  • The attributes 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.
  • The info template defines how various attribute values will appear when the graphic is clicked. Note that info templates can also be defined on a graphics layer if the end goal is to have all graphics display attribute info the same way.

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.

Optimizing code for graphics and symbols

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.