Need help with passing values to CIM symbols

1222
3
05-12-2021 07:06 AM
JamesMcClellan
New Contributor

I'm making an application that needs to display a feature layer with some complex symbols.  The symbol needs to display an icon, a colored border, and some text.  Here's an example:
CIM Symbol.png

I've written a function that creates the symbol.  It takes three variables, color, symbol, and text.  Feature layer I'm working with has values for those three variables.  The problem I have is: how do I get those values from the feature layer to the CIMsymbol?  I'm currently using a Unique Value Renderer, but that only allows me to send one value, which I'm currently using for the symbol.  I looked into using a Dictionary Renderer but that seems to use key value pairs to select symbol parts, which means that I would have to make a colored border symbol for every color in the rainbow, and a text symbol for every text value in the layer.  That's definitely unworkable as the text values and colors are input by users and change frequently.

What is the best way to hook my CIMSymbol up to my feature layer and pass the values it needs?

Here is the code for my function.
 

function getSymbol(color, symbol, text) {
	return {
		type: "CIMPointSymbol",
		symbolLayers: [
			{
				type: "CIMVectorMarker",
				enable: true,
				anchorPointUnits: "Relative",
				dominantSizeAxis3D: "Y",
				size: 30,
				billboardMode3D: "FaceNearPlane",
				frame: {
					xmin: 0,
					ymin: 0,
					xmax: 15,
					ymax: 15
				},
				markerGraphics: [
					{
						type: "CIMMarkerGraphic",
						geometry: {
							rings: [[[0, 15], [15, 15], [15, 0], [0, 0], [0, 15]]]
						},
						symbol: {
							type: "CIMPolygonSymbol",
							symbolLayers: [
								{
									type: "CIMSolidStroke",
									enable: true,
									capStyle: "Round",
									joinStyle: "Round",
									lineStyle3D: "Strip",
									miterLimit: 10,
									width: 1,
									color: color
								},
							]
						}
					}
				],
				scaleSymbolsProportionally: true,
				respectFrame: true
			},
			{
				type: "CIMPictureMarker",
				enable: true,
				anchorPoint: {"x": 0, "y": 0, "z": 0},
				anchorPointUnits: "Relative",
				dominantSizeAxis3D: "Y",
				size: 30,
				billboardMode3D: "FaceNearPlane",
				invertBackfaceTexture: true,
				scaleX: 1,
				textureFilter: "Text",
				tintColor: [255, 255, 255, 255],
				url: symbol
			},
			{
				type: "CIMVectorMarker",
				enable: true,
				size: 12,
				colorLocked: true,
				anchorPointUnits: "Relative",
				frame: {
					xmin: 0,
					ymin: 0,
					xmax: 15,
					ymax: 15
				},
				markerGraphics: [
					{
						type: "CIMMarkerGraphic",
						geometry: {
							x: 0,
							y: 0
						},
						symbol: {
							type: "CIMTextSymbol",
							fontFamilyName: "Arial",
							fontStyleName: "Bold",
							height: 10,
							horizontalAlignment: "Center",
							offsetX: 8,
							offsetY: 37.5,
							symbol: {
								type: "CIMPolygonSymbol",
								symbolLayers: [
									{
										type: "CIMSolidFill",
										enable: true,
										color: [
											255,
											255,
											255,
											255
										]
									}
								]
							},
							verticalAlignment: "Center",
							font: {
								family: "Arial",
								decoration: "none",
								style: "normal",
								weight: "bold"
							}
						},
						textString: text
					}
				],
				scaleSymbolsProportionally: true,
				respectFrame: true
			},
			{
				type: "CIMVectorMarker",
				enable: true,
				anchorPointUnits: "Relative",
				dominantSizeAxis3D: "Y",
				size: 30,
				billboardMode3D: "FaceNearPlane",
				frame: {
					xmin: 0,
					ymin: 0,
					xmax: 15,
					ymax: 15
				},
				markerGraphics: [
					{
						type: "CIMMarkerGraphic",
						geometry: {
							rings: [[[0, 5], [15, 5], [15, 0], [0, 0], [0, 5]]]
						},
						symbol: {
							type: "CIMPolygonSymbol",
							symbolLayers: [
								{
									type: "CIMSolidStroke",
									enable: true,
									capStyle: "Round",
									joinStyle: "Round",
									lineStyle3D: "Strip",
									miterLimit: 10,
									width: 1,
									color: color
								},
								{
									type: "CIMSolidFill",
									enable: true,
									color: [
										0,
										0,
										0,
										255
									]
								}
							]
						}
					}
				],
				scaleSymbolsProportionally: true,
				respectFrame: true,
				"offsetX": 0,
				"offsetY": 34
			},
		]
	};
}

 

0 Kudos
3 Replies
AnneFitz
Esri Regular Contributor

Hi James! I'm happy to hear that you're using CIM Symbols. To use attributes from your feature layer in the CIM symbol, you can use primitiveOverrides. Here's an example: https://developers.arcgis.com/javascript/latest/sample-code/cim-primitive-overrides/ 

The primitiveOverrides are set on the CIMSymbolReference of the CIMSymbol (line 223 in the sandbox of the example above). Set the primitiveName to match the primitiveName of the symbol layer you want to override, and set the propertyName to the property of that symbol layer that you are targeting. Then, use the valueExpressionInfo.expression property to access attributes from your FeatureLayer. This will take an Arcade expression if you want to do more complex calculations with your feature, or you can just return $feature.FIELDNAME.

Hope this helps/makes sense! Let me know if you have further questions!

JamesMcClellan
New Contributor

This was a big help.  I managed to get the color working using a primitiveOverride, but not the symbol or text.  According to the known limitations on the CIMSymbol, primitiveOverride wont work for some properties.
https://developers.arcgis.com/javascript/latest/api-reference/esri-symbols-CIMSymbol.html#known-limi... 
Do you know if there's any documentation anywhere that might give more insight on which properties can or cannot be overridden with a primitiveOverride?

0 Kudos
AnneFitz
Esri Regular Contributor

Glad that helped! I believe it should also work for symbol and text. Here's an example showing how to override the text https://codepen.io/annefitz/pen/abJvRaN (click on the map and more symbols will appear with the overridden text). The primitive override for the textString starts around line 143.

For the symbol - are you trying to override a specific property on the symbol? Or can you explain a little more what you're trying to do there? 

I think the documentation for what can/cannot be overridden needs some updating (I'll work on that), but I believe what you're trying to do should be supported.

0 Kudos