GraphicElement

Summary

Graphic elements are basic shapes such as points, lines, and polygons. The GraphicElement object provides access to properties and methods for managing graphic elements on a layout or in a map graphics layer.

Discussion

The GraphicElement object includes items such as points, lines, and area shapes that are added to a layout or a graphics layer. The listElements method on the Layout object returns a Python list of element objects. You must then iterate through each item in the list or specify an index number to reference a specific element. To return a list of only GraphicElement objects, use the GRAPHIC_ELEMENT constant for the element_type parameter. A wildcard value can also be used to further refine the search based on the element's name value. Give each element a unique name so it can be referenced using ArcPy scripting.

Use one of the following methods to create graphic elements:

  • The createGraphicElement method on the ArcGISProject class allows you to create a graphic element by providing a Multipoint, Point, Polygon, or Polyline geometry.
  • The createPredefinedGraphicElement method on the ArcGISProject class allows you to create a preconfigured shape such as a circle, ellipse, or triangle, for example. Create these shapes by specifying a Point value or a Polygon value.
  • Existing graphic elements can be cloned using the clone method on the GraphicElement object. This is useful because, in some cases, it is easier to start with an existing element. When cloning an element, provide a suffix value so that cloned elements can be identified later using the listElements method using a wildcard and the same suffix value. The returned list of elements can be further modified or deleted using the delete method.

There are two basic techniques when specifying the geometry to be used when creating graphic elements. The first is passing in the complete geometry that defines the graphic element. This is necessary, for example, when you are creating a point, multipoint, or custom area shape. If you are creating a predefined shape such as a rectangle, you can instead pass in a point geometry and set the elementWidth and elementHeight properties to complete the desired shape, rather than calculating and passing in all the coordinates needed to create the geometry. The point coordinate will represent the anchor position for the element and are persisted with the elementPositionX and elementPositionY properties.

Graphic elements have getDefinition and setDefinition methods that allow you to modify additional properties that are not exposed to the GraphicElement class. See the Python CIM access help topic for more information.

Note:

Prior to ArcGIS AllSource version 3.2, group elements in a layout had a type value of GRAPHIC_ELEMENT. Starting at ArcGIS AllSource version 3.2, the new GroupElement class has a type value of GROUP_ELEMENT. Graphic elements continue to support isGroup to aid with forward compatibility.

Properties

PropertyExplanationData Type
anchor
(Read Only)

Returns one of the following string values that represent the current anchor position. To change the value, use the setAnchor method.

  • BOTTOM_LEFT_CORNERBottom left corner position
  • BOTTOM_MID_POINTBottom center position
  • BOTTOM_RIGHT_CORNERBottom right corner position
  • CENTER_POINTCenter position
  • LEFT_MID_POINTLeft center position
  • RIGHT_MID_POINTRight center position
  • TOP_LEFT_CORNERTop left corner position
  • TOP_MID_POINTTop center position
  • TOP_RIGHT_CORNERTop right corner position
String
elementHeight
(Read and Write)

The height of the element in either layout page units or map units.

Double
elementPositionX
(Read and Write)

The x-location of the element's anchor position in either layout page units or map units.

Double
elementPositionY
(Read and Write)

The y-location of the element's anchor position in either layout page units or map units.

Double
elementRotation
(Read and Write)

The element's rotation angle in degrees. Positive values rotate clockwise and negative values rotate counterclockwise.

Double
elementWidth
(Read and Write)

The width of the element in either layout page units or map units.

Double
isGroup
(Read Only)

Returns True if the element is a GroupElement. It is not possible to clone or delete group elements.

Boolean
locked
(Read and Write)

When set to True, the element cannot be graphically selected in the layout or map view.

Boolean
longName
(Read Only)

An element's full name including group information if it exists. For example, an element named 'Point' in a group element named 'Group Element' will return a longName value of 'Group Element\\Point'. If the element is not in a group, the longName will be the same as the name value.

String
name
(Read and Write)

The name of the element. It is important that all elements have a unique name so they can be uniquely referenced using the wildcard parameter with the listElements function on the Layout object.

String
parentGroupElement
(Read Only)

If the element is in a group, the value returned will be a GroupElement.

GroupElement
type
(Read Only)

Returns a value of GRAPHIC_ELEMENT.

String
visible
(Read and Write)

Controls if the element is visible in the layout or graphics layer.

Boolean

Method Overview

MethodExplanation
applyStyleItem (style_item)

The applyStyleItem method applies a style item to a graphic element.

clone ({suffix})

Provides a mechanism to clone an existing graphic element on a page layout.

delete ()

Provides a mechanism to delete an existing graphic element on a page layout.

getDefinition (cim_version)

Returns a graphic element's CIM definition.

setAnchor (anchor)

The setAnchor method controls the anchor position for a GraphicElement.

setDefinition (definition_object)

Sets a graphic element's CIM definition.

Methods

applyStyleItem (style_item)
ParameterExplanationData Type
style_item

A reference to a StyleItem in a project.

StyleItem

When referencing a StyleItem using the listStyleItems method on the ArcGISProject class, the style_class parameter must be POINT, LINE, or POLYGON. Because a graphic element supports multiple geometry types and you might be iterating through a number of elements in a loop, you may need to determine the geometry type before applying a style. The code sample below demonstrates how to do this. For more information and code samples, refer the to StyleItem help topic.

Note:

Styles must be added to a project prior to using the applyStyleItem method. They can be added using the updateStyles method on the ArcGISProject class.

The following script iterates through graphic elements in a layout and uses Python CIM access to determine the graphic element's geometry type before applying a style item to each element.

p = arcpy.mp.ArcGISProject('current')
lyt = p.listLayouts('*_Layout')[0]

poly_si = p.listStyleItems('ArcGIS 2D', 'Polygon', 'Park')[0]
line_si = p.listStyleItems('Favorites', 'Line', 'Trail')[0]
pt_si = p.listStyleItems('Favorites', 'Point', 'First Aid')[0]
multiPt_si = p.listStyleItems('Favorites', 'Point', 'Water')[0]
for elm in lyt.listElements('GRAPHIC_ELEMENT'):
  elm_cim = elm.getDefinition('V3')
  if isinstance(elm_cim.graphic, arcpy.cim.CIMGraphics.CIMPolygonGraphic):
    elm.applyStyleItem(poly_si)
  if isinstance(elm_cim.graphic, arcpy.cim.CIMGraphics.CIMLineGraphic):    
    elm.applyStyleItem(line_si)
  if isinstance(elm_cim.graphic, arcpy.cim.CIMGraphics.CIMPointGraphic):    
    elm.applyStyleItem(pt_si)
  if isinstance(elm_cim.graphic, arcpy.cim.CIMGraphics.CIMMultipointGraphic):    
    elm.applyStyleItem(multiPt_si)
clone ({suffix})
ParameterExplanationData Type
suffix

An optional string that is used to tag each newly created graphic element. The new element will get the same element name as the parent graphic plus the suffix value along with a numeric sequencer. For example, if the parent element name is Line and the suffix value is _copy, the newly cloned elements are named Line_copy, Line_copy_1, Line_copy_2, and so on. If a suffix is not provided, the results resemble Line_1, Line_2, Line_3, and so on.

String

Grouped text elements can't be cloned. All grouped elements are graphic element types. Verify if a graphic element is grouped by using the isGroup property on the GraphicElement object.

delete ()

It may be necessary to delete existing or cloned graphic elements. Cloned elements, when created, can be given a custom suffix so they can be easy to find when using the wildcard parameter for the listElements method on the Layout object.

getDefinition (cim_version)
ParameterExplanationData Type
cim_version

A string that represents the major version of the CIM that will be used.

  • V2The 2.x version of the CIM will be used.
  • V3The 3.x version of the CIM will be used.
String
Return Value
Data TypeExplanation
Object

Returns the CIM definition for a GraphicElement.

For more information about working with the CIM and samples, see Python CIM access.

setAnchor (anchor)
ParameterExplanationData Type
anchor

A string that specifies the location of the anchor position.

  • BOTTOM_LEFT_CORNERThe anchor will be set at the bottom left corner position.
  • BOTTOM_MID_POINTThe anchor will be set at the bottom center position.
  • BOTTOM_RIGHT_CORNERThe anchor will be set at the bottom right corner position.
  • CENTER_POINTThe anchor will be set at the center position.
  • LEFT_MID_POINTThe anchor will be set at the left center position.
  • RIGHT_MID_POINTThe anchor will be set at the right center position.
  • TOP_LEFT_CORNERThe anchor will be set at the top left corner position.
  • TOP_MID_POINTThe anchor will be set at the top center position.
  • TOP_RIGHT_CORNERThe anchor will be set at the top right corner position.
String

Setting the anchor position is helpful because you can control how the element might expand when resized. For example, the default anchor position for a graphic element is BOTTOM_LEFT_CORNER. If you change the anchor location to TOP_RIGHT_CORNER, changing elementHeight will expand the element downward, and changing elementWidth will expand the element to the left.

setDefinition (definition_object)
ParameterExplanationData Type
definition_object

A modified CIM definition object originally retrieved using getDefinition.

Object

For more information about working with the CIM and samples, see Python CIM access.

Code sample

GraphicElement example 1

The following script moves a group element named Grouped Graphics to a new location on the page layout using a new anchor position and saves the changes.

p = arcpy.mp.ArcGISProject('CURRENT')
lyt = p.listLayouts('Graphic*')[0]
elm = lyt.listElements('GROUP_ELEMENT', 'Grouped Graphics')[0]
elm.setAnchor('Center_Point')
elm.elementPositionX = 3.25
elm.elementPositionY = 9.5
GraphicElement example 2

The following script creates a point graphic element in a new layout. The script then creates a point graphic element in a graphics layer in a new map.

p = arcpy.mp.ArcGISProject('current')

#Create a layout
lyt = p.createLayout(8.5, 11, 'INCH', 'New Layout with Point')

ptStyle = p.listStyleItems('ArcGIS 2D', 'Point', 'Star 1')[0]

#Construct a layout point graphic element using a default symbol
lyt_ptGra = p.createGraphicElement(lyt, arcpy.Point(4.125, 5.5),
                               ptStyle, 'ArcPy_Point')
#Optional - modify the symbol size via the CIM
lyt_ptGra_cim = lyt_ptGra.getDefinition('V3')
lyt_ptGra_cim.graphic.symbol.symbol.symbolLayers[0].size = 150
lyt_ptGra.setDefinition(lyt_ptGra_cim)

lyt.openView()


#Create a map (WGS 1984 Web Mecator) and graphics layer
m = p.createMap('New Map with Point', 'Map')
gl = m.createGraphicsLayer('New Graphics Layer')

#Construct a point in map space
map_ptGra = p.createGraphicElement(gl, arcpy.Point(-13681707, 5947924),
                               ptStyle, 'Olympia Capitol Building')

#Optional - modify the symbol size via the CIM
map_ptGra_cim = map_ptGra.getDefinition('V3')
map_ptGra_cim.graphic.symbol.symbol.symbolLayers[0].size = 25
map_ptGra.setDefinition(map_ptGra_cim)

m.openView()
GraphicElement example 3

The following script constructs a multipoint graphic element with 48 points in a new layout and modifies the symbol size using Python CIM access.

p = arcpy.mp.ArcGISProject('current')
lyt = p.createLayout(100, 100, 'CENTIMETER', 'X Marks the Spot')

#Construct 2 multi-point graphic elements using a system style item
mPtStyle = p.listStyleItems('ArcGIS 2D', 'Point', 'X Marker')[0]

x = 4; y = 4; z = 96
mPtCoords = []
for i in range(1, 25):
    xy = [x, y]
    xz = [x, z]
    mPtCoords.append(xy)
    mPtCoords.append(xz)
    x = x + 4
    y = y + 4
    z = z - 4
mPt = arcpy.Multipoint(arcpy.Array([arcpy.Point(*coords)
                                    for coords in mPtCoords]))
mPtGra = p.createGraphicElement(lyt, mPt, mPtStyle, name='ArcPy_MultiPt')

#Optional - modify the point symbol size via the CIM
mPtGra_cim = mPtGra.getDefinition('V3')
mPtGra_cim.graphic.symbol.symbol.symbolLayers[0].size = 75
mPtGra.setDefinition(mPtGra_cim)

lyt.openView()
GraphicElement example 4

The following script constructs a polyline graphic element in a new layout and modifies its symbol layers using Python CIM access.

p = arcpy.mp.ArcGISProject('current')
lyt = p.createLayout(5, 3, 'INCH', 'New layout with line graphic')

#Construct a line graphic element using a sytem style item
lnStyle = p.listStyleItems('ArcGIS 2D', 'Line', 'Line with 2 Markers')[0]
plyLnCoords = [[1, 1.25], [2, 2], [3, 1], [4, 1.5]]
plyLn = arcpy.Polyline(arcpy.Array([arcpy.Point(*coords)
                                    for coords in plyLnCoords]))
lnGra = p.createGraphicElement(lyt, plyLn, lnStyle, 'ArcPy_Line')

#Optional - modify multiple line symbol layer properties via the CIM
lnGra_cim = lnGra.getDefinition('V3')
lnSym = lnGra_cim.graphic.symbol.symbol
lnSym.symbolLayers[0].size = 20
lnSym.symbolLayers[0].markerPlacement.offsetAlongLine = 60
lnSym.symbolLayers[0].markerPlacement.placementTemplate = [240]
lnSym.symbolLayers[1].size = 20
lnSym.symbolLayers[1].markerPlacement.offsetAlongLine = 180
lnSym.symbolLayers[1].markerPlacement.placementTemplate = [240]
lnSym.symbolLayers[2].effects[0].dashTemplate = [80, 40, 80, 40]
lnSym.symbolLayers[2].width = 4
lnGra.setDefinition(lnGra_cim)

lyt.openView()
GraphicElement example 5

The following script uses a JSON template to create a curve (arc) and a Bézier geometry. The geometries are used to create two graphic elements in a new layout. Optionally, Python CIM access is used to modify the Bézier curve properties. For more information about creating geometry objects using JSON, see Geometry objects.

p = arcpy.mp.ArcGISProject('current')
lyt = p.createLayout(6, 3, 'INCH', 'New Layout with 2 curves')

#Construct a curve/arc graphic element using a default symbol
arcPath = {"curvePaths" : [[[3.5,1.25],{"c" : [[5,1.25],[4.25, 1.75]]}]]}
arc = arcpy.AsShape(arcPath, esri_json=True)
arcGra = p.createGraphicElement(lyt, arc, name='ArcPy_Arc')

#Construct a bezier curve graphic element using a system style item
curveStyle = p.listStyleItems('ArcGIS 2D', 'Line', 'Dashed 1 Long 1 Short')[0]
curvePath = {"curvePaths" : [[[1.25,1.25],
                              {"b" : [[3,1.5],[1.6875,2.75],[2.125,0]]}]]}
curve = arcpy.AsShape(curvePath, esri_json=True)
curveGra = p.createGraphicElement(lyt, curve, curveStyle, 'ArcPy_Curve')

#Optional - modify the bezier curve symbol layer properties via the CIM
curveGra_cim = curveGra.getDefinition('V3')
symLyr1 = curveGra_cim.graphic.symbol.symbol.symbolLayers[0]
symLyr1.width = 4
symLyr1.color.values = [255, 0, 0, 100]
symLyr1.effects[0].dashTemplate = [8, 8, 0.01, 8]
symLyr1.capStyle = 'Round'
curveGra.setDefinition(curveGra_cim)

lyt.openView()
GraphicElement example 6

The following script constructs a polygon graphic element in a new layout and creates a new map, adds a layer file, and loads the features from the layer into a new graphics layer.

p = arcpy.mp.ArcGISProject('current')

#Create a layout
lyt = p.createLayout(8.5, 11, 'INCH', 'New Layout with Polygon')

#Construct a polygon graphic element using a system style item
polyStyle = p.listStyleItems('ArcGIS 2D', 'Polygon', 'Buffered Gradient')[0]

polyCoords = [[1, 1], [1, 10], [7.5, 10], [7.5, 9], [2, 9], [2, 6], [6.5, 6],
              [6.5, 5], [2, 5], [2, 2], [7.5, 2], [7.5, 1], [1, 1]]
poly = arcpy.Polygon(arcpy.Array([arcpy.Point(*coords)
                                  for coords in polyCoords]))
polyGra = p.createGraphicElement(lyt, poly, polyStyle, name='ArcPy_Polygon')

lyt.openView()


#Create a map, add a layer file and create a graphics layer
m = p.createMap('New Map with Feature Polygons', 'Map')
lyrFile = arcpy.mp.LayerFile(r"C:\Projects\GreatLakes\GreatLakes.lyrx")
m.addLayer(lyrFile)
lyr = m.listLayers('GreatLakes')[0]
gl = m.createGraphicsLayer('New Graphics Layer')

#Load polygon features into a map's graphics layer
#Caution - map graphics have limitations in terms of total size and number

for row in arcpy.da.SearchCursor(lyr, ["SHAPE@"]):
    featShp = row[0]
    p.createGraphicElement(gl, featShp, polyStyle)

m.openView()
GraphicElement example 7

The following script creates two predefined graphic elements in a layout. The first one is created using an envelope function, and the second uses a point location and resizes the element using the elementWidth and elementHeight properties.

def MakeRec_LL(llx, lly, w, h):
    xyRecList = [[llx, lly], [llx, lly+h], [llx+w,lly+h], [llx+w,lly], [llx,lly]]
    xyRecList = [[1,1],[1, 2], [2.75, 2], [2.75, 1], [1, 1]]
    array = arcpy.Array([arcpy.Point(*coords) for coords in xyRecList])
    rec = arcpy.Polygon(array)
    return rec

p = arcpy.mp.ArcGISProject('CURRENT')

#Create a layout
lyt = p.createLayout(6, 3, 'INCH', 'New Layout with Rectangles')

#Construct a pre-defined rectangle graphic element using a system style item
# and a rectangle function that takes x/y min/max and a width/height
# using the lower left corner as a start location

polyStyle = p.listStyleItems('ArcGIS 2D', 'Polygon', 'Orchard')[0]

p.createPredefinedGraphicElement(lyt, MakeRec_LL(1, 1, 1.75, 1), 'RECTANGLE',
                                 polyStyle, 'ArcPy_Rectangle_Env',
                                 lock_aspect_ratio=False)

#Construct the same element above using a point location
rec = p.createPredefinedGraphicElement(lyt, arcpy.Point(3, 1), 'RECTANGLE',
                                       polyStyle, 'ArcPy_Rectangle_Pt',
                                       lock_aspect_ratio=False)
rec.elementWidth = 1.75
rec.elementHeight = 1

lyt.openView()
GraphicElement example 8

The following script creates a polygon graphic element for each of the 10 predefined shapes, sets the anchor to the center position, and uses Python CIM access to update a Rounding property that is persisted within a custom propertySetItem dictionary associated with each graphic.

p = arcpy.mp.ArcGISProject('current')
lyt = p.createLayout(8.5, 11, 'INCH', 'Predefined Shapes')

#A list of pre-defined shape key words
shapeList = ['Circle', 'Cloud', 'Cross', 'Ellipse', 'Half_Circle',
             'Rectangle', 'Right_Triangle', 'Rounded_Rectangle', 'Triangle', 'X']

x = 1.25
y = 9.5
for shape in shapeList:
    elm = p.createPredefinedGraphicElement(lyt, arcpy.Point(x, y), shape, name=f'ArcPy_{shape}_Pt')
    elm.setAnchor('Center_Point')
    if elm.elementWidth > elm.elementHeight:
        elm.elementWidth = 0.75
    else:
        elm.elementHeight = 0.75

    #Optional - use Python CIM Access to modify element rounding
    elm_cim = elm.getDefinition('V3')   
    attrbs = elm_cim.graphic.attributes
    attrbs['propertySetItems'] = ['Rounding', 50]  #Sets 50% rounding
    elm.setDefinition(elm_cim)

    y = y - 1

lyt.openView()
GraphicElement example 9

The following script constructs a graphic table based on data values from a table in a map. The layout was authored with a vertical line named vertLine, a horizontal line named horzLine, and a text element named cellText. Each element was authored with the appropriate symbology and text properties. The elements' anchors were set to the upper left position and the text elements' vertical and horizontal justification were set to top left.

import arcpy
aprx = arcpy.mp.ArcGISProject(r"C:\Projects\YosemiteNP\Yosemite.aprx")

#Reference items in the project
m = aprx.listMaps("Yosemite National Park")[0]
lyr = m.listLayers("Valley_Pts")[0]
lyt = aprx.listLayouts("Points of Interest")[0]
horzLine = lyt.listElements("GRAPHIC_ELEMENT", "horzLine")[0]
vertLine = lyt.listElements("GRAPHIC_ELEMENT", "vertLine")[0]
tableText = lyt.listElements("TEXT_ELEMENT", "cellText")[0]

#Get/set information about the table
numRows = int(arcpy.GetCount_management(lyr).getOutput(0))
rowHeight = 0.2
fieldNames = ["COMPLEXID", "NAME"]
numColumns = len(fieldNames)
colWidth = 1.5

#Build graphic table lines based on upper left coordinate
#  set the proper size of the original, parent line, then clone it and position appropriately
upperX = 1.0
upperY = 5.0

#Vertical lines
vertLine.elementPositionX = upperX
vertLine.elementPositionY = upperY
vertLine.elementHeight =  (rowHeight * numRows) + rowHeight #extra line for column names

x = upperX
for vert in range(1, numColumns+1):
  x = x + colWidth
  vert_clone = vertLine.clone("_clone")
  vert_clone.elementPositionX = x

#Horizontal lines
horzLine.elementPositionX = upperX
horzLine.elementPositionY = upperY
horzLine.elementWidth = numColumns * colWidth

y = upperY - rowHeight
for horz in range(1, numRows +2 ):  #need to accommodate the extra line for field names
  temp_horz = horzLine.clone("_clone")
  temp_horz.elementPositionY = y
  y = y - rowHeight

#Place text column names
tableText.elementPositionX = upperX + 0.05 #slight offset
tableText.elementPositionY = upperY
tableText.text = fieldNames[0]
accumWidth = colWidth
for field in range(1, numColumns):
  newFieldTxt = tableText.clone("_clone")
  newFieldTxt.text = fieldNames[field]
  newFieldTxt.elementPositionX = newFieldTxt.elementPositionX + accumWidth
  accumWidth = accumWidth + colWidth

#Create text elements based on values from the table
table = arcpy.SearchCursor(lyr.dataSource)
y = upperY - rowHeight
for row in table:
  x = upperX + 0.05 #slight offset
  try:   
    for field in fieldNames:
      newCellTxt = tableText.clone("_clone")
      newCellTxt.text = row.getValue(field)
      newCellTxt.elementPositionX = x
      newCellTxt.elementPositionY = y
      accumWidth = accumWidth + colWidth
      x = x + colWidth
    y = y - rowHeight
  except:
    print("Invalid value assignment")

#Export to PDF and delete cloned elements
lyt.exportToPDF(r"C:\Temp\test.pdf")

for elm in lyt.listElements(wildcard="_clone"):
  elm.delete()
del aprx