skills/arcgis-visualization/SKILL.md
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.
npx skillsauth add SaschaBrunnerCH/arcgis-maps-sdk-js-ai-context arcgis-visualizationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when styling layers with renderers, symbols, visual variables, labels, and effects.
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";
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, replaceimport X from "path"withconst X = await $arcgis.import("path").
| 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) |
const renderer = {
type: "simple",
symbol: {
type: "simple-marker",
color: "blue",
size: 8,
outline: {
color: "white",
width: 1,
},
},
};
layer.renderer = renderer;
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 },
],
},
],
};
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",
},
],
};
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,
};
}
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",
},
],
};
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
};
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",
},
};
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,
},
};
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
};
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,
},
};
const symbol = {
type: "picture-marker",
url: "https://example.com/icon.png",
width: 24,
height: 24,
xoffset: 0,
yoffset: 0,
};
const symbol = {
type: "text",
text: "Label",
color: "white",
font: {
family: "Arial",
size: 12,
weight: "bold",
},
haloColor: "black",
haloSize: 1,
};
// 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,
},
],
};
const symbol = {
type: "web-style",
name: "Pushpin 1",
styleName: "Esri2DPointSymbolsStyle",
};
const symbol = {
type: "mesh-3d",
symbolLayers: [
{
type: "fill",
material: { color: [244, 247, 134] },
},
],
};
const symbol = {
type: "line-3d",
symbolLayers: [
{
type: "path",
profile: "quad", // circle, quad
material: { color: "red" },
width: 5,
height: 5,
},
],
};
const symbol = {
type: "polygon-3d",
symbolLayers: [
{
type: "extrude",
material: { color: "blue" },
size: 100, // Extrusion height
},
],
};
Visual variable classes: ColorVariable, SizeVariable, OpacityVariable, RotationVariable.
import ColorVariable from "@arcgis/core/renderers/visualVariables/ColorVariable.js";
import SizeVariable from "@arcgis/core/renderers/visualVariables/SizeVariable.js";
visualVariables: [
{
type: "size",
field: "magnitude",
stops: [
{ value: 1, size: 4 },
{ value: 5, size: 20 },
{ value: 10, size: 40 },
],
},
];
visualVariables: [
{
type: "color",
field: "temperature",
stops: [
{ value: 0, color: "blue" },
{ value: 50, color: "yellow" },
{ value: 100, color: "red" },
],
},
];
visualVariables: [
{
type: "opacity",
field: "confidence",
stops: [
{ value: 0, opacity: 0.1 },
{ value: 100, opacity: 1 },
],
},
];
visualVariables: [
{
type: "rotation",
field: "heading",
rotationType: "geographic", // or "arithmetic"
},
];
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;
above-center, below-center, center-center, above-left, etc.above-along, below-along, center-alongalways-horizontallabelExpressionInfo: {
expression: `
var pop = $feature.population;
if (pop > 1000000) {
return $feature.name + " (" + Round(pop/1000000, 1) + "M)";
}
return $feature.name;
`;
}
All symbol and renderer objects support autocasting - use plain objects instead of constructing classes.
// 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:
layer.renderer = {
type: "simple",
symbol: {
type: "simple-marker",
color: "red",
size: 8,
},
} as const;
When you need instance methods, use explicit classes:
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.
get-started-visualization - Getting started with data visualizationvisualization-classbreaks - ClassBreaksRenderer for numeric datavisualization-unique-value-groups - Grouped unique value renderersvisualization-vv-color - Visual variables with colorvisualization-pie-chart - PieChartRenderer for multivariate datavisualization-heatmap - Heatmap visualizationvisualization-dot-density - Dot density mapsvisualization-point-styles - Point symbol styleslabels-basic - Basic label configurationlabels-multiline - Multiline labelslabels-multiple-classes - Multiple label classesMissing type property: Both renderers and symbols require a type property for autocasting.
// Anti-pattern: missing type on renderer and symbol
layer.renderer = {
symbol: { color: "red", size: 8 },
};
// 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.
Color formats: Colors can be hex, named, RGB array, or RGBA array.
color: "red";
color: "#FF0000";
color: [255, 0, 0];
color: [255, 0, 0, 0.5]; // With transparency
Visual variables require numeric fields: Using a string field for size or color produces no variation.
// 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 },
],
},
];
// Correct: numeric field for size
visualVariables: [
{
type: "size",
field: "population", // Numeric field
stops: [
{ value: 10000, size: 4 },
{ value: 1000000, size: 40 },
],
},
];
Label expressions are Arcade: Use Arcade syntax ($feature.fieldName), not JavaScript.
3D symbols need SceneView: PointSymbol3D, LineSymbol3D, PolygonSymbol3D only work in SceneView, not MapView.
arcgis-cim-symbols - Advanced cartographic symbols (CIM)arcgis-smart-mapping - Auto-generated renderers from dataarcgis-feature-effects - Visual effects and filtersarcgis-core-maps - Map and view setuparcgis-layers - Layer types and configurationdevelopment
Build map user interfaces with ArcGIS widgets, Map Components, and Calcite Design System. Use for adding legends, layer lists, search, tables, time sliders, and custom UI layouts.
development
Add specialized widgets including BuildingExplorer, FloorFilter, Track, Locate, HistogramRangeSlider, ScaleBar, Compass, NavigationToggle, and media viewers. Use for building exploration, indoor mapping, GPS tracking, and data histograms.
tools
Work with ArcGIS Utility Networks for modeling and analyzing connected infrastructure including network tracing, associations visualization, and topology validation. Use for electric, gas, water, and telecom network analysis.
data-ai
Work with temporal data using TimeSlider, TimeExtent, TimeInterval, and time-aware layers. Use for animating data over time, filtering by date ranges, and visualizing temporal patterns.