Dynamic Placement of Polygon Labels

296
2
Jump to solution
12-20-2023 07:12 AM
JeffreyThompson2
MVP Regular Contributor

I have a polygon FeatureLayer with labels turned on. The labels appear to be fixed in position at the centroid of the polygon.

JeffreyThompson2_0-1703084462373.png

I would like them to reposition themselves, so that the label is always visible regardless of the zoom level. So a zoomed in view like this is still labeled.

JeffreyThompson2_1-1703084584722.png

Is this supported by the API? According to the documentation, the only polygon label placement option is 'always-horizontal'. https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-LabelClass.html#la...

This seems like very basic behavior so I'd be surprised if it's not supported. Any suggestions or work-arounds?

GIS Developer
City of Arlington, Texas
1 Solution

Accepted Solutions
JeffreyThompson2
MVP Regular Contributor

I have developed a workaround. The FeatureLayer in my case is created from a MapImageLayer and a MapImageLayer does handle dynamic repositioning. I have used the MapImageLayer to effectively create a layer that only contains labels and loaded it to my map as well as the FeatureLayer which handles all the other attributes on the map.

This creates a MapImageLayer with only the sublayer I want and hides everything but the labels.

//Label only mapImageLayer
const mapImage = new MapImageLayer({
   url: 'url',
   listMode: hide,
   sublayers: [
                    {
                        id: 8,
                        legendEnabled: false,
                        listMode: 'hide',
                        opacity: 0
                    }
                ]

 I gave my FeatureLayer a LabelClass with a labelExpressionInfo of an empty string to trick it into thinking it's doing the labeling.

labelClass: [
    {
        labelExpressionInfo: {
            expression: ' '
        },
        symbol: {
            type: 'text',
            color: 'black',
            font: {
                family: 'Noto Sans',
                size: 7,
                weight: 'normal'
            }
        },
        labelPlacement: 'always-horizontal'
    }
]

And I used reactiveUtils to turn on/off the MapImageLayer when the layer it is tied to or its labels are turned on/off.

sublayer8 = mapImage.findSublayerById(8)
feature8 = jimuMapView.view.map.findLayerById('featureLayer8')
reactiveUtils.watch(() => [feature8?.visible, feature8?.labelsVisible], ([visible, labels]) => {
	if (visible && labels) {
		sublayer8.visible = true
	} else {
		sublayer8.visible = false
	}
})
GIS Developer
City of Arlington, Texas

View solution in original post

0 Kudos
2 Replies
SaurabhUpadhyaya
Occasional Contributor

I am also facing the same issue, trying to fixe the label position dynamically.

Also facing the issue, label text is not displaying correctly in print map. Can anyone suggest .

0 Kudos
JeffreyThompson2
MVP Regular Contributor

I have developed a workaround. The FeatureLayer in my case is created from a MapImageLayer and a MapImageLayer does handle dynamic repositioning. I have used the MapImageLayer to effectively create a layer that only contains labels and loaded it to my map as well as the FeatureLayer which handles all the other attributes on the map.

This creates a MapImageLayer with only the sublayer I want and hides everything but the labels.

//Label only mapImageLayer
const mapImage = new MapImageLayer({
   url: 'url',
   listMode: hide,
   sublayers: [
                    {
                        id: 8,
                        legendEnabled: false,
                        listMode: 'hide',
                        opacity: 0
                    }
                ]

 I gave my FeatureLayer a LabelClass with a labelExpressionInfo of an empty string to trick it into thinking it's doing the labeling.

labelClass: [
    {
        labelExpressionInfo: {
            expression: ' '
        },
        symbol: {
            type: 'text',
            color: 'black',
            font: {
                family: 'Noto Sans',
                size: 7,
                weight: 'normal'
            }
        },
        labelPlacement: 'always-horizontal'
    }
]

And I used reactiveUtils to turn on/off the MapImageLayer when the layer it is tied to or its labels are turned on/off.

sublayer8 = mapImage.findSublayerById(8)
feature8 = jimuMapView.view.map.findLayerById('featureLayer8')
reactiveUtils.watch(() => [feature8?.visible, feature8?.labelsVisible], ([visible, labels]) => {
	if (visible && labels) {
		sublayer8.visible = true
	} else {
		sublayer8.visible = false
	}
})
GIS Developer
City of Arlington, Texas
0 Kudos