Skip to main content

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 Pro version 3.2, group elements in a layout had a type value of GRAPHIC_ELEMENT. Starting at ArcGIS Pro 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

Name Explanation Data 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_CORNER—Bottom left corner position

  • BOTTOM_MID_POINT—Bottom center position

  • BOTTOM_RIGHT_CORNER—Bottom right corner position

  • CENTER_POINT—Center position

  • LEFT_MID_POINT—Left center position

  • RIGHT_MID_POINT—Right center position

  • TOP_LEFT_CORNER—Top left corner position

  • TOP_MID_POINT—Top center position

  • TOP_RIGHT_CORNER—Top 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

Methods

applyStyleItem(style_item)

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

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.

Name Explanation Data type

style_item

A reference to a StyleItem in a project.

StyleItem

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})

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

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.

Name Explanation Data type

suffix

(Optional)

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

delete()

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

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)

Returns a graphic element's CIM definition.

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

Name Explanation Data type

cim_version

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

  • V2—The 2.x version of the CIM will be used.

  • V3—The 3.x version of the CIM will be used.

String

Return value

Data type Explanation

Object

Returns the CIM definition for a GraphicElement.

setAnchor(anchor)

The setAnchor method controls the anchor position for a GraphicElement.

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.

Name Explanation Data type

anchor

A string that specifies the location of the anchor position.

  • BOTTOM_LEFT_CORNER—The anchor will be set at the bottom left corner position.

  • BOTTOM_MID_POINT—The anchor will be set at the bottom center position.

  • BOTTOM_RIGHT_CORNER—The anchor will be set at the bottom right corner position.

  • CENTER_POINT—The anchor will be set at the center position.

  • LEFT_MID_POINT—The anchor will be set at the left center position.

  • RIGHT_MID_POINT—The anchor will be set at the right center position.

  • TOP_LEFT_CORNER—The anchor will be set at the top left corner position.

  • TOP_MID_POINT—The anchor will be set at the top center position.

  • TOP_RIGHT_CORNER—The anchor will be set at the top right corner position.

String

setDefinition(definition_object)

Sets a graphic element's CIM definition.

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

Name Explanation Data type

definition_object

A modified CIM definition object originally retrieved using getDefinition.

Object

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.management.GetCount(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