ArcGIS CIM Symbols
Use this skill for creating advanced cartographic symbols with CIM (Cartographic Information Model).
CIM Symbol Basics
CIM symbols provide advanced cartographic capabilities:
-
Multi-layer symbols
-
Complex marker graphics
-
Custom line patterns
-
Animated symbols
-
Data-driven symbol properties
Basic CIM Symbol
const graphic = new Graphic({ geometry: point, symbol: { type: "cim", data: { type: "CIMSymbolReference", symbol: { type: "CIMPointSymbol", symbolLayers: [{ type: "CIMVectorMarker", enable: true, size: 20, frame: { xmin: 0, ymin: 0, xmax: 10, ymax: 10 }, markerGraphics: [{ type: "CIMMarkerGraphic", geometry: { rings: [[[0,0], [10,0], [10,10], [0,10], [0,0]]] }, symbol: { type: "CIMPolygonSymbol", symbolLayers: [{ type: "CIMSolidFill", enable: true, color: [255, 0, 0, 255] }] } }] }] } } } });
CIM Point Symbols
Numbered Marker
function getNumberedMarkerCIM(number) { return { type: "CIMSymbolReference", primitiveOverrides: [{ type: "CIMPrimitiveOverride", primitiveName: "textGraphic", propertyName: "TextString", valueExpressionInfo: { type: "CIMExpressionInfo", expression: "$feature.text", returnType: "Default" } }], symbol: { type: "CIMPointSymbol", symbolLayers: [ // Text layer (on top) { type: "CIMVectorMarker", enable: true, size: 32, frame: { xmin: -5, ymin: -5, xmax: 5, ymax: 5 }, markerGraphics: [{ type: "CIMMarkerGraphic", primitiveName: "textGraphic", geometry: { x: 0, y: 0 }, symbol: { type: "CIMTextSymbol", fontFamilyName: "Arial", fontStyleName: "Bold", height: 4, horizontalAlignment: "Center", verticalAlignment: "Center", symbol: { type: "CIMPolygonSymbol", symbolLayers: [{ type: "CIMSolidFill", enable: true, color: [255, 255, 255, 255] }] } }, textString: String(number) }] }, // Circle background { type: "CIMVectorMarker", enable: true, size: 24, frame: { xmin: 0, ymin: 0, xmax: 10, ymax: 10 }, markerGraphics: [{ type: "CIMMarkerGraphic", geometry: { rings: [/* circle coordinates */] }, symbol: { type: "CIMPolygonSymbol", symbolLayers: [{ type: "CIMSolidFill", enable: true, color: [0, 100, 200, 255] }] } }] } ] } }; }
Pin Marker
const pinMarkerCIM = { type: "CIMSymbolReference", symbol: { type: "CIMPointSymbol", symbolLayers: [{ type: "CIMVectorMarker", enable: true, anchorPoint: { x: 0, y: -0.5 }, anchorPointUnits: "Relative", size: 40, frame: { xmin: 0, ymin: 0, xmax: 20, ymax: 30 }, markerGraphics: [{ type: "CIMMarkerGraphic", geometry: { rings: [[ [10, 30], [0, 15], [0, 10], [10, 0], [20, 10], [20, 15], [10, 30] ]] }, symbol: { type: "CIMPolygonSymbol", symbolLayers: [ { type: "CIMSolidStroke", enable: true, width: 1, color: [50, 50, 50, 255] }, { type: "CIMSolidFill", enable: true, color: [255, 100, 100, 255] } ] } }] }] } };
CIM Line Symbols
Arrow Line
const arrowLineCIM = { type: "CIMSymbolReference", symbol: { type: "CIMLineSymbol", symbolLayers: [ // Arrow head at end { type: "CIMVectorMarker", enable: true, size: 12, markerPlacement: { type: "CIMMarkerPlacementAtExtremities", extremityPlacement: "JustEnd", angleToLine: true }, frame: { xmin: 0, ymin: 0, xmax: 10, ymax: 10 }, markerGraphics: [{ type: "CIMMarkerGraphic", geometry: { rings: [[[0, 0], [10, 5], [0, 10], [3, 5], [0, 0]]] }, symbol: { type: "CIMPolygonSymbol", symbolLayers: [{ type: "CIMSolidFill", enable: true, color: [0, 0, 0, 255] }] } }] }, // Line stroke { type: "CIMSolidStroke", enable: true, width: 2, color: [0, 0, 0, 255] } ] } };
Dashed Line with Pattern
const dashedLineCIM = { type: "CIMSymbolReference", symbol: { type: "CIMLineSymbol", symbolLayers: [{ type: "CIMSolidStroke", enable: true, width: 3, color: [0, 100, 200, 255], effects: [{ type: "CIMGeometricEffectDashes", dashTemplate: [8, 4, 2, 4], // dash, gap, dash, gap lineDashEnding: "NoConstraint" }] }] } };
CIM Polygon Symbols
Hatched Fill
const hatchedFillCIM = { type: "CIMSymbolReference", symbol: { type: "CIMPolygonSymbol", symbolLayers: [ // Hatch pattern { type: "CIMHatchFill", enable: true, lineSymbol: { type: "CIMLineSymbol", symbolLayers: [{ type: "CIMSolidStroke", enable: true, width: 1, color: [0, 0, 0, 255] }] }, rotation: 45, separation: 5 }, // Background fill { type: "CIMSolidFill", enable: true, color: [255, 255, 200, 255] }, // Outline { type: "CIMSolidStroke", enable: true, width: 2, color: [0, 0, 0, 255] } ] } };
Marker Placement
Along Line
const markerAlongLine = { type: "CIMVectorMarker", enable: true, size: 10, markerPlacement: { type: "CIMMarkerPlacementAlongLineSameSize", placementTemplate: [20], // Every 20 points angleToLine: true }, // ... marker graphics };
At Vertices
const markerAtVertices = { type: "CIMVectorMarker", enable: true, size: 8, markerPlacement: { type: "CIMMarkerPlacementAtRatioPositions", positionArray: [0, 0.5, 1], // Start, middle, end angleToLine: true }, // ... marker graphics };
Animated CIM Symbols
// Animation is controlled via animatedSymbolProperties on symbol layers const animatedCIM = { type: "CIMSymbolReference", symbol: { type: "CIMPointSymbol", symbolLayers: [{ type: "CIMVectorMarker", enable: true, size: 20, // Animation properties animatedSymbolProperties: { type: "CIMAnimatedSymbolProperties", playAnimation: true, reverseAnimation: false, randomizeStartTime: true, startTimeOffset: 0, duration: 3, // Seconds repeatType: "Loop" // Loop, Oscillate, None }, // ... marker graphics }] } };
// Scale animation const scaleAnimation = { type: "CIMVectorMarker", animatedSymbolProperties: { type: "CIMAnimatedSymbolProperties", playAnimation: true, duration: 2, repeatType: "Oscillate" }, scaleSymbolsProportionally: true, // ... marker definition };
Data-Driven Properties
Color from Attribute
const dataDrivenCIM = {
type: "CIMSymbolReference",
primitiveOverrides: [{
type: "CIMPrimitiveOverride",
primitiveName: "fillLayer",
propertyName: "Color",
valueExpressionInfo: {
type: "CIMExpressionInfo",
expression: var val = $feature.value; if (val < 50) return [255, 0, 0, 255]; if (val < 100) return [255, 255, 0, 255]; return [0, 255, 0, 255]; ,
returnType: "Default"
}
}],
symbol: {
type: "CIMPointSymbol",
symbolLayers: [{
type: "CIMVectorMarker",
markerGraphics: [{
type: "CIMMarkerGraphic",
symbol: {
type: "CIMPolygonSymbol",
symbolLayers: [{
type: "CIMSolidFill",
primitiveName: "fillLayer",
enable: true,
color: [128, 128, 128, 255] // Default
}]
}
}]
}]
}
};
Size from Attribute
primitiveOverrides: [{ type: "CIMPrimitiveOverride", primitiveName: "mainMarker", propertyName: "Size", valueExpressionInfo: { type: "CIMExpressionInfo", expression: "Sqrt($feature.population) * 0.01", returnType: "Default" } }]
Common CIM Properties
Colors
// RGBA array [R, G, B, A] where each value is 0-255 color: [255, 0, 0, 255] // Red, fully opaque color: [0, 0, 255, 128] // Blue, 50% transparent
Stroke Properties
{ type: "CIMSolidStroke", enable: true, width: 2, color: [0, 0, 0, 255], capStyle: "Round", // Butt, Round, Square joinStyle: "Round", // Bevel, Miter, Round miterLimit: 10 }
Anchor Points
{ anchorPoint: { x: 0, y: 0 }, // Center anchorPoint: { x: 0, y: -0.5 }, // Bottom center anchorPointUnits: "Relative" // Relative or Absolute }
TypeScript Usage
CIM symbols are plain objects by design (following CIM specification). For TypeScript safety, use as const or type annotations:
Using as const
const cimSymbol = { type: "cim", data: { type: "CIMSymbolReference", symbol: { type: "CIMPointSymbol", symbolLayers: [{ type: "CIMVectorMarker", enable: true, size: 20, // ... rest of symbol definition }] } } } as const;
Using Type Annotation
const cimSymbol: __esri.CIMSymbolProperties = { type: "cim", data: { type: "CIMSymbolReference", symbol: { type: "CIMPointSymbol", symbolLayers: [{ type: "CIMVectorMarker", enable: true, size: 20, // ... rest of symbol definition }] } } };
Note: CIM symbols are configuration objects and work well with autocasting. Use as const to keep discriminated union types narrow in TypeScript. See arcgis-core-maps skill for detailed guidance on autocasting.
Reference Samples
-
cim-symbols
-
Basic CIM symbol creation
-
cim-animations
-
Animated CIM symbols
-
cim-line-arrows
-
Arrow symbols for line features
-
cim-primitive-overrides
-
CIM primitive override patterns
-
cim-marker-placement
-
Marker placement along lines
Common Pitfalls
Frame coordinates: Frame defines the coordinate space for marker graphics
Layer order: Symbol layers render bottom to top in the array
Primitive names: Must be unique within symbol for overrides to work
Color format: Always use [R, G, B, A] with values 0-255
Geometry rings: Rings must be closed (first point = last point)