摘要
图形元素是点、线和面等基础形状。 可通过 GraphicElement 对象访问属性和方法,这些属性和方法用于管理布局上或地图图形图层中的图形元素。
说明
GraphicElement 对象包含多种项目,例如点、线和添加到布局或图形图层中的区域形状。 Layout 对象上的 listElements 方法用于返回元素对象的 Python 列表。 然后,您必须遍历列表中的每个项目,或指定一个索引编号以引用特定元素。 要仅返回 GraphicElement 对象的列表,应对 element_type 参数使用 GRAPHIC_ELEMENT 常量。 还可以使用 wildcard 值,基于元素的 name 值对搜索进行进一步优化。 为每个元素提供一个唯一名称,以使元素可以通过 ArcPy 脚本引用。
使用以下方法之一创建图形元素:
- 您可以使用 ArcGISProject 类上的 createGraphicElement 方法,通过提供 Multipoint、Point、Polygon 或 Polyline 几何来创建图形元素。
- 您可以使用 ArcGISProject 类上的 createPredefinedGraphicElement 方法创建预配置的形状,例如圆形、椭圆或三角形。 可通过指定 Point 值或 Polygon 值来创建这些形状。
- 可以使用 GraphicElement 对象的 clone 方法克隆现有图形元素。 此方法十分有用,因为在某些情况下,从现有元素开始操作会更加容易。 克隆元素时,请提供 suffix 值以使克隆的元素后续可以通过 listElements 方法使用通配符和相同的 suffix 值进行识别。 可以使用 delete 方法进一步修改或删除返回的元素列表。
创建图形元素时,可以使用两种基本方法指定要使用的几何。 第一种方法是传入定义图形元素的完整几何。 当您要创建点、多点或自定义区域形状时,此为必要步骤。 如要创建预定义形状(如矩形),则可以改为传入点几何并设置 elementWidth 和 elementHeight 属性以完成所需的形状,而无需计算并传入创建几何所需的所有坐标。 点坐标将表示元素的 anchor 位置,将通过 elementPositionX 和 elementPositionY 属性保留。
图形元素具有 getDefinition 和 setDefinition 方法,可用于修改未向 GraphicElement 类暴露的附加属性。 有关详细信息,请参阅 Python CIM 访问帮助主题。
注:
在 ArcGIS Pro 3.2 之前的版本中,布局中的组元素 type 值为 GRAPHIC_ELEMENT。 从 ArcGIS Pro 3.2 版本开始,新 GroupElement 类的 type 值为 GROUP_ELEMENT。 图形元素继续支持 isGroup 以帮助实现向前兼容。
属性
属性 | 说明 | 数据类型 |
anchor (只读) | 返回表示当前锚点位置的以下字符串值之一。 要更改值,请使用 setAnchor 方法。
| String |
elementHeight (可读写) | 采用布局页面单位或地图单位的元素高度。 | Double |
elementPositionX (可读写) | 采用布局页面单位或地图单位的元素锚点位置的 x 位置。 | Double |
elementPositionY (可读写) | 采用布局页面单位或地图单位的元素锚点位置的 y 位置。 | Double |
elementRotation (可读写) | 元素旋转角度(以度为单位)。 正值将使方向顺时针旋转,负值将使方向逆时针旋转。 | Double |
elementWidth (可读写) | 采用布局页面单位或地图单位的元素宽度。 | Double |
isGroup (只读) | 如果元素是 True,则返回 GroupElement。 无法 clone 或 delete 组元素。 | Boolean |
locked (可读写) | 设置为 True 时,无法在布局或地图视图中以图形方式选择元素。 | Boolean |
longName (只读) | 元素的全名,包括组信息(如果存在)。 例如,在一个名称为 Point 的组元素中,名称为 Group Element 的元素将返回 Group Element\\Point 的 longName 值。 如果元素不在组中,则 longName 与 name 值相同。 | String |
name (可读写) | 元素的名称。 必须确保所有元素均具有唯一名称,因为这样可以通过在 Layout 对象的 listElements 函数中使用 wildcard 参数以唯一方式引用这些元素。 | String |
parentGroupElement (只读) | 如果元素在组中,则返回的值将为 GroupElement。 | GroupElement |
type (只读) | 返回值 GRAPHIC_ELEMENT。 | String |
visible (可读写) | 控制元素是否在布局或图形图层中可见。 | Boolean |
方法概述
方法 | 说明 |
applyStyleItem (style_item) | applyStyleItem 方法可将样式项应用到图形元素上。 |
clone ({suffix}) | 提供了一种克隆页面布局中现有图形元素的机制。 |
delete () | 提供了一种删除页面布局中现有图形元素的机制。 |
getDefinition (cim_version) | 返回图形元素的 CIM 定义。 |
setAnchor (anchor) | setAnchor 方法可控制 GraphicElement 的锚点位置。 |
setDefinition (definition_object) | 设置图形元素的 CIM 定义。 |
方法
applyStyleItem (style_item)
当在 ArcGISProject 类上使用 listStyleItems 方法引用 StyleItem 时,style_class 参数必须是 POINT、LINE 或 POLYGON。 由于图形元素支持多种几何类型,并且您可能在循环中遍历多个元素,因此您可能需要在应用样式之前确定几何类型。 下面的代码示例演示了此操作方法。 有关详细信息和代码示例,请参阅 StyleItem 帮助主题。
注:
在使用 applyStyleItem 方法之前,必须先将样式添加到工程中。 可以在 ArcGISProject 类上使用 updateStyles 方法添加样式。
以下脚本遍历布局中的图形元素,并使用 Python CIM 访问来确定图形元素的几何类型,然后再对每个元素应用样式项。
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})
参数 | 说明 | 数据类型 |
suffix | 用于标记每个新建图形元素的可选字符串。新元素的元素名为父项图形元素加上 suffix 值以及数值定序符。例如,如果父元素名称为 Line 且 suffix 值为 _copy,则新克隆的元素的名称为 Line_copy、Line_copy_1、Line_copy_2 等。如果未提供 suffix,则名称类似于 Line_1、Line_2、Line_3 等。 | String |
无法克隆分组的文本元素。所有分组元素都是图形元素类型。使用 GraphicElement 对象中的 isGroup 属性验证图形元素是否分组。
delete ()
可能需要删除现有或已克隆的图形元素。创建克隆元素时,可为克隆元素指定自定义 suffix,以便在对 Layout 对象上的 listElements 方法使用 wildcard 参数时可轻松找到这些元素。
getDefinition (cim_version)
参数 | 说明 | 数据类型 |
cim_version | A string that represents the major version of the CIM that will be used.
| String |
数据类型 | 说明 |
Object | 返回 GraphicElement 的 CIM 定义。 |
有关使用 CIM 和示例的详细信息,请参阅 Python CIM 访问。
setAnchor (anchor)
参数 | 说明 | 数据类型 |
anchor | A string that specifies the location of the anchor position.
| String |
设置锚点位置非常有用,因为您可以控制元素在调整大小时的展开方式。 例如,图形元素的默认锚点位置为 BOTTOM_LEFT_CORNER。 如果将锚点位置更改为 TOP_RIGHT_CORNER,则更改 elementHeight 将使元素向下扩展,更改 elementWidth 将使元素向左扩展。
setDefinition (definition_object)
参数 | 说明 | 数据类型 |
definition_object | A modified CIM definition object originally retrieved using getDefinition. | Object |
有关使用 CIM 和示例的详细信息,请参阅 Python CIM 访问。
代码示例
以下脚本可使用新的锚点位置将名为 Grouped Graphics 的组元素移动到页面布局上的新位置,然后保存更改。
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
以下脚本可在新布局中创建一个点图形元素。 然后,脚本可在新地图的图形图层中创建一个点图形元素。
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()
以下脚本可在新布局中使用 48 个点构建多点图形元素,并使用 Python CIM 访问修改符号大小。
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()
以下脚本可在新布局中构建折线图形元素,并使用 Python CIM 访问修改其符号图层。
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()
以下脚本可使用 JSON 模板创建一个曲线 (arc) 和一个贝塞尔曲线几何。 该几何用于在新布局中创建两个图形元素。 可以选择性地使用 Python CIM 访问修改贝塞尔曲线的属性。 有关使用 JSON 创建几何对象的详细信息,请参阅几何对象。
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()
以下脚本可在新布局中构建一个面图形元素,创建新地图,添加图层文件,然后将图层中的元素加载到新的图形图层中。
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()
以下脚本可在布局中创建两个预定义图形元素。 第一个图形元素使用包络矩形函数创建,第二个图形元素使用点位置,并使用 elementWidth 和 elementHeight 属性重新调整大小。
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()
以下脚本会为 10 个预定义形状中的每个形状创建一个面图形元素,将锚点设置为中心位置,然后使用 Python CIM 访问更新 Rounding 属性,该属性保存在与各个图形关联的自定义 propertySetItem 字典中。
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()
以下脚本可以基于地图中某个表的数据值构建图形表。 使用名为 vertLine 的垂直线、名为 horzLine 的水平线和名为 cellText 的文本元素制作布局。 每个元素使用相应的符号系统和文本属性进行创作。 元素锚点设置为左上角位置,文本元素的垂直和水平对齐设置为左上角对齐。
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