# Arcgis Visualization

> Style and render geographic data with renderers, symbols, and visual variables. Use for creating thematic maps, heatmaps, class breaks, unique values, labels, and 3D visualization.

- Skill: `saschabrunnerch/arcgis-visualization` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add saschabrunnerch/arcgis-visualization`
- Raw SKILL.md: https://api.skillmd.com/api/skills/saschabrunnerch/arcgis-visualization/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: saschabrunnerch (https://skillmd.com/u/saschabrunnerch)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/saschabrunnerch/arcgis-visualization

---


# ArcGIS Visualization

Use this skill when styling layers with renderers, symbols, visual variables, labels, and effects.

## Import Patterns

### Direct ESM Imports

```javascript
import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
import UniqueValueRenderer from "@arcgis/core/renderers/UniqueValueRenderer.js";
import ClassBreaksRenderer from "@arcgis/core/renderers/ClassBreaksRenderer.js";
import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";
import SimpleLineSymbol from "@arcgis/core/symbols/SimpleLineSymbol.js";
import SimpleFillSymbol from "@arcgis/core/symbols/SimpleFillSymbol.js";
```

### CDN Dynamic Imports

```javascript
const [SimpleRenderer, SimpleMarkerSymbol] = await $arcgis.import([
  "@arcgis/core/renderers/SimpleRenderer.js",
  "@arcgis/core/symbols/SimpleMarkerSymbol.js",
]);
```

> **Note:** Examples below use autocasting (plain objects with `type`). For CDN usage, replace `import X from "path"` with `const X = await $arcgis.import("path")`.

## Renderer Types Overview

| Renderer            | Autocast Type    | Use Case                            |
| ------------------- | ---------------- | ----------------------------------- |
| SimpleRenderer      | `"simple"`       | Same symbol for all features        |
| UniqueValueRenderer | `"unique-value"` | Different symbols by category       |
| ClassBreaksRenderer | `"class-breaks"` | Different symbols by numeric ranges |
| HeatmapRenderer     | `"heatmap"`      | Density visualization (points only) |
| DotDensityRenderer  | `"dot-density"`  | Dot density maps (polygons only)    |
| PieChartRenderer    | `"pie-chart"`    | Pie charts per feature              |
| DictionaryRenderer  | `"dictionary"`   | Military symbology (MIL-STD-2525)   |
| FlowRenderer        | `"flow"`         | Animated flow lines (imagery)       |

## SimpleRenderer

```javascript
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: "blue",
    size: 8,
    outline: {
      color: "white",
      width: 1,
    },
  },
};

layer.renderer = renderer;
```

### With Visual Variables

```javascript
const renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: "#13EB0C",
    outline: { color: "#A9A9A9", width: 0.5 },
  },
  visualVariables: [
    {
      type: "size",
      field: "population",
      stops: [
        { value: 1000, size: 4 },
        { value: 10000, size: 12 },
        { value: 100000, size: 24 },
      ],
    },
  ],
};
```

## UniqueValueRenderer

### Basic Unique Values

```javascript
const renderer = {
  type: "unique-value",
  field: "type",
  defaultSymbol: { type: "simple-fill", color: "gray" },
  uniqueValueInfos: [
    {
      value: "residential",
      symbol: { type: "simple-fill", color: "#FFFF00" },
      label: "Residential",
    },
    {
      value: "commercial",
      symbol: { type: "simple-fill", color: "#FF0000" },
      label: "Commercial",
    },
    {
      value: "industrial",
      symbol: { type: "simple-fill", color: "#800080" },
      label: "Industrial",
    },
  ],
};
```

### Grouped Unique Values (with headings in legend)

```javascript
const renderer = {
  type: "unique-value",
  field: "zonecode",
  uniqueValueGroups: [
    {
      heading: "Commercial",
      classes: [
        {
          label: "C-1 | Neighborhood Commercial",
          symbol: createFillSymbol([189, 145, 145]),
          values: "C-1",
        },
        {
          label: "C-2 | Community Commercial",
          symbol: createFillSymbol([255, 179, 219]),
          values: "C-2",
        },
      ],
    },
    {
      heading: "Residential",
      classes: [
        {
          label: "R-1 | Low Density",
          symbol: createFillSymbol([255, 255, 224]),
          values: "R-1",
        },
        {
          label: "Special Areas",
          symbol: createFillSymbol([161, 237, 237]),
          values: ["S-DW", "S-DR", "S-RP"], // Multiple values
        },
      ],
    },
  ],
};

function createFillSymbol(color) {
  return {
    type: "simple-fill",
    color: color,
    outline: null,
  };
}
```

## ClassBreaksRenderer

```javascript
const renderer = {
  type: "class-breaks",
  field: "population",
  normalizationField: "area", // Optional: divide by this field
  legendOptions: {
    title: "Population Density",
  },
  defaultSymbol: {
    type: "simple-fill",
    color: "black",
    style: "backward-diagonal",
  },
  defaultLabel: "No data",
  classBreakInfos: [
    {
      minValue: 0,
      maxValue: 100,
      symbol: { type: "simple-fill", color: "#fffcd4" },
      label: "< 100",
    },
    {
      minValue: 100,
      maxValue: 500,
      symbol: { type: "simple-fill", color: "#b1cdc2" },
      label: "100 - 500",
    },
    {
      minValue: 500,
      maxValue: 1000,
      symbol: { type: "simple-fill", color: "#38627a" },
      label: "500 - 1,000",
    },
    {
      minValue: 1000,
      maxValue: Infinity,
      symbol: { type: "simple-fill", color: "#0d2644" },
      label: "> 1,000",
    },
  ],
};
```

## HeatmapRenderer

```javascript
const renderer = {
  type: "heatmap",
  colorStops: [
    { color: "rgba(63, 40, 102, 0)", ratio: 0 },
    { color: "#472b77", ratio: 0.083 },
    { color: "#563098", ratio: 0.25 },
    { color: "#7139d4", ratio: 0.5 },
    { color: "#853fff", ratio: 0.664 },
    { color: "#c29f80", ratio: 0.83 },
    { color: "#ffff00", ratio: 1 },
  ],
  maxDensity: 0.01,
  minDensity: 0,
  radius: 18, // Blur radius in pixels
};
```

## PieChartRenderer

```javascript
const renderer = {
  type: "pie-chart",
  attributes: [
    { field: "asian_pop", label: "Asian", color: "#ed5151" },
    { field: "black_pop", label: "Black", color: "#149ece" },
    { field: "white_pop", label: "White", color: "#a7c636" },
    { field: "other_pop", label: "Other", color: "#9e559c" },
  ],
  size: 18,
  othersCategory: {
    threshold: 0.05,
    color: "gray",
    label: "Other",
  },
};
```

## 2D Symbol Types

### SimpleMarkerSymbol (Points)

```javascript
const symbol = {
  type: "simple-marker",
  style: "circle", // circle, square, cross, x, diamond, triangle
  color: [255, 0, 0],
  size: 12,
  outline: {
    color: [255, 255, 255],
    width: 2,
  },
};
```

### SimpleLineSymbol

```javascript
const symbol = {
  type: "simple-line",
  style: "solid", // solid, dash, dot, dash-dot, etc.
  color: [0, 0, 255],
  width: 2,
  cap: "round", // round, butt, square
  join: "round", // round, miter, bevel
};
```

### SimpleFillSymbol (Polygons)

```javascript
const symbol = {
  type: "simple-fill",
  style: "solid", // solid, none, horizontal, vertical, cross, etc.
  color: [255, 255, 0, 0.5], // RGBA
  outline: {
    type: "simple-line",
    color: [0, 0, 0],
    width: 1,
  },
};
```

### PictureMarkerSymbol

```javascript
const symbol = {
  type: "picture-marker",
  url: "https://example.com/icon.png",
  width: 24,
  height: 24,
  xoffset: 0,
  yoffset: 0,
};
```

### TextSymbol

```javascript
const symbol = {
  type: "text",
  text: "Label",
  color: "white",
  font: {
    family: "Arial",
    size: 12,
    weight: "bold",
  },
  haloColor: "black",
  haloSize: 1,
};
```

## 3D Symbol Types

### PointSymbol3D

```javascript
// Icon marker
const symbol = {
  type: "point-3d",
  symbolLayers: [
    {
      type: "icon",
      resource: { primitive: "circle" },
      material: { color: "red" },
      size: 12,
    },
  ],
};

// Object marker
const objectSymbol = {
  type: "point-3d",
  symbolLayers: [
    {
      type: "object",
      resource: { primitive: "cylinder" }, // cone, cube, sphere, diamond
      material: { color: "blue" },
      height: 100,
      width: 10,
      depth: 10,
    },
  ],
};
```

### WebStyleSymbol (3D icons from gallery)

```javascript
const symbol = {
  type: "web-style",
  name: "Pushpin 1",
  styleName: "Esri2DPointSymbolsStyle",
};
```

### MeshSymbol3D (for SceneLayer)

```javascript
const symbol = {
  type: "mesh-3d",
  symbolLayers: [
    {
      type: "fill",
      material: { color: [244, 247, 134] },
    },
  ],
};
```

### LineSymbol3D

```javascript
const symbol = {
  type: "line-3d",
  symbolLayers: [
    {
      type: "path",
      profile: "quad", // circle, quad
      material: { color: "red" },
      width: 5,
      height: 5,
    },
  ],
};
```

### PolygonSymbol3D

```javascript
const symbol = {
  type: "polygon-3d",
  symbolLayers: [
    {
      type: "extrude",
      material: { color: "blue" },
      size: 100, // Extrusion height
    },
  ],
};
```

## Visual Variables

Visual variable classes: `ColorVariable`, `SizeVariable`, `OpacityVariable`, `RotationVariable`.

```javascript
import ColorVariable from "@arcgis/core/renderers/visualVariables/ColorVariable.js";
import SizeVariable from "@arcgis/core/renderers/visualVariables/SizeVariable.js";
```

### Size Variable

```javascript
visualVariables: [
  {
    type: "size",
    field: "magnitude",
    stops: [
      { value: 1, size: 4 },
      { value: 5, size: 20 },
      { value: 10, size: 40 },
    ],
  },
];
```

### Color Variable

```javascript
visualVariables: [
  {
    type: "color",
    field: "temperature",
    stops: [
      { value: 0, color: "blue" },
      { value: 50, color: "yellow" },
      { value: 100, color: "red" },
    ],
  },
];
```

### Opacity Variable

```javascript
visualVariables: [
  {
    type: "opacity",
    field: "confidence",
    stops: [
      { value: 0, opacity: 0.1 },
      { value: 100, opacity: 1 },
    ],
  },
];
```

### Rotation Variable

```javascript
visualVariables: [
  {
    type: "rotation",
    field: "heading",
    rotationType: "geographic", // or "arithmetic"
  },
];
```

## Labeling

```javascript
layer.labelingInfo = [
  {
    symbol: {
      type: "text",
      color: "white",
      font: {
        family: "Noto Sans",
        size: 10,
        weight: "bold",
      },
      haloColor: "#472b77",
      haloSize: 1,
    },
    labelPlacement: "above-center", // Various placement options
    labelExpressionInfo: {
      expression: "$feature.name", // Arcade expression
    },
    where: "population > 10000", // SQL filter
    minScale: 500000,
    maxScale: 0,
  },
];

layer.labelsVisible = true;
```

### Label Placements

- Points: `above-center`, `below-center`, `center-center`, `above-left`, etc.
- Lines: `above-along`, `below-along`, `center-along`
- Polygons: `always-horizontal`

### Arcade Label Expressions

```javascript
labelExpressionInfo: {
  expression: `
    var pop = $feature.population;
    if (pop > 1000000) {
      return $feature.name + " (" + Round(pop/1000000, 1) + "M)";
    }
    return $feature.name;
  `;
}
```

## Autocasting

All symbol and renderer objects support autocasting - use plain objects instead of constructing classes.

```javascript
// Autocast: plain object with type property
layer.renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: "red",
    size: 8,
  },
};
```

For TypeScript, use `as const` or `satisfies`:

```typescript
layer.renderer = {
  type: "simple",
  symbol: {
    type: "simple-marker",
    color: "red",
    size: 8,
  },
} as const;
```

When you need instance methods, use explicit classes:

```javascript
import SimpleRenderer from "@arcgis/core/renderers/SimpleRenderer.js";
import SimpleMarkerSymbol from "@arcgis/core/symbols/SimpleMarkerSymbol.js";

layer.renderer = new SimpleRenderer({
  symbol: new SimpleMarkerSymbol({ color: "red", size: 8 }),
});
```

> For layer effects (bloom, blur, drop-shadow) and blend modes, see `arcgis-feature-effects`.

> For smart mapping renderers and data-driven visualization, see `arcgis-smart-mapping`.

> For advanced cartographic symbols with CIM, see `arcgis-cim-symbols`.

## Reference Samples

- `get-started-visualization` - Getting started with data visualization
- `visualization-classbreaks` - ClassBreaksRenderer for numeric data
- `visualization-unique-value-groups` - Grouped unique value renderers
- `visualization-vv-color` - Visual variables with color
- `visualization-pie-chart` - PieChartRenderer for multivariate data
- `visualization-heatmap` - Heatmap visualization
- `visualization-dot-density` - Dot density maps
- `visualization-point-styles` - Point symbol styles
- `labels-basic` - Basic label configuration
- `labels-multiline` - Multiline labels
- `labels-multiple-classes` - Multiple label classes

## Common Pitfalls

1. **Missing type property**: Both renderers and symbols require a `type` property for autocasting.

   ```javascript
   // Anti-pattern: missing type on renderer and symbol
   layer.renderer = {
     symbol: { color: "red", size: 8 },
   };
   ```

   ```javascript
   // Correct: include type at both renderer and symbol level
   layer.renderer = {
     type: "simple",
     symbol: {
       type: "simple-marker",
       color: "red",
       size: 8,
     },
   };
   ```

   **Impact:** Without `type`, autocasting fails silently. Features render with default symbology.

2. **Color formats**: Colors can be hex, named, RGB array, or RGBA array.

   ```javascript
   color: "red";
   color: "#FF0000";
   color: [255, 0, 0];
   color: [255, 0, 0, 0.5]; // With transparency
   ```

3. **Visual variables require numeric fields**: Using a string field for size or color produces no variation.

   ```javascript
   // Anti-pattern: string field for size
   visualVariables: [
     {
       type: "size",
       field: "city_name", // String field - no variation
       stops: [
         { value: 0, size: 4 },
         { value: 100, size: 40 },
       ],
     },
   ];
   ```

   ```javascript
   // Correct: numeric field for size
   visualVariables: [
     {
       type: "size",
       field: "population", // Numeric field
       stops: [
         { value: 10000, size: 4 },
         { value: 1000000, size: 40 },
       ],
     },
   ];
   ```

4. **Label expressions are Arcade**: Use Arcade syntax (`$feature.fieldName`), not JavaScript.

5. **3D symbols need SceneView**: PointSymbol3D, LineSymbol3D, PolygonSymbol3D only work in SceneView, not MapView.

## Related Skills

- `arcgis-cim-symbols` - Advanced cartographic symbols (CIM)
- `arcgis-smart-mapping` - Auto-generated renderers from data
- `arcgis-feature-effects` - Visual effects and filters
- `arcgis-core-maps` - Map and view setup
- `arcgis-layers` - Layer types and configuration

