Essential ArcGIS Online WebMap Layer Labeling with the ArcGIS API for Python

Table of Contents

The Video

Introduction

The ArcGIS API for Python is a powerful Python library that allows users to interact with and automate tasks in ArcGIS Online (or Portal). The API is excellent for programmatically creating, maintaining, and updating webmaps and feature layers in ArcGIS Online. In this post we will focus on updating labels in a webmap layer! 

Automate ArcGIS Online WebMap Workflows with the ArcGIS API for Python | A Complete Guide from Beginner to Advanced | Full Course

Free on YouTube! A set of videos detailing ArcGIS Online WebMap workflows using the ArcGIS API for Python. We will do a deep dive into properties and methods available, along with custom workflows for automating with WebMaps and the ArcGIS API for Python.

The ArcGIS API for Python version 2.4 introduced the Map class as a replacement for the WebMap class from previous versions. The Map class has a property called content that is the MapContent class that aids with accessing, managing, and updating components of WebMap layers and tables. The update_layer() method is at the heart of being able to update layers for various elements such as symbology (renederer), forms, transparency, layer titles, and labelling amongst others. Unfortunately, as of writing this article (v2.4.1.1), updating the labels has a bug. But that can’t stop us from updating labels for a layer via the WebMap definition. 

The video above explores the current bug with the update_layer(label_info) parameter and how we can use the Item object get_data() method to access the WebMap definition as a Python dictionary, manipulate the labelingInfo property for a layer and ultimately update labels in a WebMap.

labelingInfo property

The labelingInfo property is a list that can contain dictionaries that represent a label class for a layer in a WebMap. We will look at the minimum viable label class properties required as shown below.

				
					label_info = [
    {
        "labelExpression": "[COUNTY]", # only used if labelExpressionInfo is missing
        "symbol": {
            "type": "esriTS",
            "color": [
                0,
                0,
                0,
                255
            ]
        }
    }
]
				
			

We will build upon this minimum definition to manipulate labels for a layer relating to:

  • Arcade Expressions
  • Fonts (family, size, weight, style)
  • Halo
  • Angle
  • Offsets
  • Background
  • Scale Range
  • Filtering

WebMap Specification

The WebMap Specification is an excellent resource for finding out what properties are available for labels. For example, in the ArcGIS Online GUI we cannot set a label angle or underline text, but we can set these with code. We must also note that we cannot use all the properties that are listed in the specification, some simply do not work, but I implore you to test them out. These properties could be signs of what is to come, and they probably work if you’re building a WebMap with the JavaScript SDK for ArcGIS.

If you’ve found these blogs helpful and would like to support the project, please consider making a donation. All learning material is provided free of charge to help GIS professionals, students, and developers learn ArcPy, the ArcGIS API for Python, ArcGIS Pro, and ArcGIS Online. Donations help cover website hosting, software licensing, domain costs, and the time involved in creating and maintaining tutorials, courses, and learning resources. Your support helps keep this content freely available to everyone and allows new courses and materials to be developed for the GIS community. If the content has helped you solve a problem, learn a new skill, or advance your career, please consider supporting the project with a donation. Every contribution, no matter the size, is greatly appreciated.

All the code in one place

				
					from arcgis.gis import GIS

################################################################################
## API Reference Links:
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#gis
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.ContentManager.get
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#item
##  https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html#arcgis.gis.Item.get_data
##  https://developers.arcgis.com/web-map-specification/objects/labelingInfo/
##
################################################################################

## Access ArcGIS Online
agol = GIS("home")

## get the WebMap content item as an Item object
wm_item = agol.content.get("WM_ITEMID")

################################################################################
## labelingInfo definition
################################################################################

label_info = [
    {
        "name" : "County Names", # the name of the label class
        "labelExpression": "[COUNTY]", # only used if labelExpressionInfo is missing
##        "labelExpressionInfo": {
##            "expression": "$feature[\"COUNTY\"]",
##        },
        "labelExpressionInfo": {
            "expression": "\"Co. \" + Proper($feature[\"COUNTY\"])", # arcade expression
            "title" : "Co. Expression" # the name/title of the expression
        },
        "symbol": {
            "type": "esriTS", # the only type available - Esri Text Symbol
            "color": [
                0, # R
                0, # G
                0, # B
                255 # Alpha (transparency)
            ],
            "font": {
                "family": "Arial",
                "size": 12, # size is in points
                "weight" : "bold", # bold, bolder, lighter, normal
                "style" : "italic", # italic, normal, oblique
                "decoration" : "underline" # line-through, none, underline
            },
            "haloColor": [
                255,
                255,
                0,
                255
            ],
            "haloSize": 1,
            "angle": 45, # East and counter-clockwise
            "xoffset": 50, # in points
            "yoffset": 50, # in points
            "backgroundColor" : [ # adds coloured rectangle the lable
                0,
                0,
                0,
                255
            ],
            "borderLineColor" : [ # adds an outline colour to the backgroundColor
                255,
                255,
                0,
                255
            ],
            "borderLineSize" : 1
        },
        "maxScale" : 100000, # scale range
        "minScale" : 10000000, # scale range
        "where" : "PROVINCE = 'Leinster'" # filter
    }
]

################################################################################
## Applying the labels
################################################################################

## get the WebMap definition as a Python Dictionary
wm_item_data = wm_item.get_data()

## for each layer definition (dict) in the operationalLayers (list)
for lyr_def in wm_item_data["operationalLayers"]:

    ## if the title of the layer matches where we want to update/apply labels
    if lyr_def["title"] == "County Boundaries":

        ## display the labels
        lyr_def["showLabels"] = True

        ## set the labelingInfo ################################################

        ## check if layerDefinition exists in the layer properties
        if "layerDefinition" in lyr_def:
            ## if it does, then check for a drawingInfo property
            if "drawingInfo" in lyr_def["layerDefinition"]:
                ## update labelingInfo property if drawingInfo exists
                lyr_def["layerDefinition"]["drawingInfo"]["labelingInfo"] = label_info
            ## otherwise create the draingInfo property and the labelingInfo
            else:
                lyr_def["layerDefinition"]["drawingInfo"] = {"labelingInfo" : label_info}
        ## if not, create the properties
        else:
            lyr_def["layerDefinition"] = {"drawingInfo" : {"labelingInfo" : label_info}}

## update the WebMap Definition with the altered layer properties
wm_item.update(
    item_properties = {"text" : wm_item_data}
)

################################################################################
print("\nSCRIPT COMPLETE")
				
			

Leave a Comment