Colors & Classification
A CHOROPLETH or CHART layer maps a value field to a color. This guide covers the two halves of that mapping: classification (how values are grouped into classes) and color schemes (which colors those classes get).
Continuous vs. discrete classification
How the value→color mapping is done depends on whether the data is continuous numeric or discrete categorical.
Continuous numeric values — a number that can take any value in a range (population, temperature, GDP). Classification groups the range into classes and assigns a colour to each class:
| Method | How classes are built |
|---|---|
EQUIDISTANT |
Equal-width intervals across the data range |
QUANTILE |
Equal-count — same number of features per class |
HEADTAIL |
Iterative mean split — best for heavy-tailed distributions |
NATURAL |
Jenks natural breaks — minimises within-class variance |
LOG |
Logarithmic intervals — for data spanning orders of magnitude |
// Continuous: 5 quantile classes, yellow → dark blue
.type("CHOROPLETH|QUANTILE")
.style({ colorscheme: ["#ffffcc","#41b6c4","#253494"], showdata: "true" })Discrete categorical values — a label or code that belongs to a fixed set ("forest", "urban", "water"; or species names, party names, land-use codes). Use CATEGORICAL and pair it with a values array that maps each category to a colour slot:
// Discrete: three categories, each pinned to a colour
.type("CHART|BUBBLE|CATEGORICAL")
.style({
colorscheme: ["#4fc3f7", "#ffb300", "#ef5350"],
values: ["low", "medium", "high"], // strings — not numbers!
showdata: "true"
})values must be strings
iXMaps matches category values as strings. Numeric categories like 1, 2, 3 are silently ignored — always pass ["1","2","3"].
The classification methods work with both CHOROPLETH (polygon fill) and CHART (symbol colour).
In all cases — continuous or discrete — the colour scheme maps to classes in order: first colour → first class, second colour → second class, and so on. With continuous methods the classes are numeric ranges computed automatically; with CATEGORICAL the classes are the entries in the values array. The colour assignment mechanism is the same.
To set class breaks explicitly instead of computing them, use the ranges style property (n+1 values for n classes) — see Style Properties.
Color schemes
The colorscheme property accepts several formats.
Single color
colorscheme: ["#0066cc"] // single hex color
colorscheme: ["blue"] // named colorGradient (two colors, auto-interpolated)
colorscheme: ["5", "#ffffcc", "#253494"] // 5 classes, yellow → dark blue
colorscheme: ["#fee5d9", "#a50f15"] // implied 2-class gradientThe first element can be a number (class count) or omitted; iXMaps infers it from the array length.
Multi-stop palette
colorscheme: ["#ffffcc","#c7e9b4","#41b6c4","#2c7fb8","#253494"] // 5 explicit colorsNamed palettes
colorscheme: ["5", "tableau10"] // 5 classes from Tableau 10
colorscheme: ["7", "viridis"] // 7 classes viridis
colorscheme: ["7", "plasma"] // 7 classes plasma
colorscheme: ["100", "tableau"] // auto-palette, 100 classesCATEGORICAL color binding
For categorical data, the values array pins specific categories to specific colors (in the same order as colorscheme):
.type("CHART|BUBBLE|CATEGORICAL")
.style({
colorscheme: ["#4fc3f7", "#ffb300", "#ef5350"],
values: ["low", "medium", "high"], // strings — not numbers!
showdata: "true"
})values with CATEGORICAL
Without values, iXMaps assigns colors by order of first occurrence — unpredictable and data-order dependent.
Always cast values to strings: ["1","2","3"] not [1,2,3].
Diverging scales
Use an even number of colors and set rangecentervalue:
.style({
colorscheme: ["#d73027","#f46d43","#fdae61","#abd9e9","#74add1","#4575b4"],
rangecentervalue: 0,
showdata: "true"
})Flow line gradients
For CHART|VECTOR|BEZIER|GRADIENT, use linecolor as a two-element array — not colorscheme:
.type("CHART|VECTOR|BEZIER|POINTER|GRADIENT")
.style({
linecolor: ["#00aabb", "#ff4400"], // origin color → destination color
showdata: "true"
})Data-driven colorschemes
Every format above is a static palette, fixed when you write .style({...}). For a palette computed from the layer’s own data — e.g. color assigned by matching each class’s label against a pattern, once the classes are actually known — pass a function reference instead of colors:
.style({ colorscheme: "ixmaps.colorScheme_speedmap" })Define the function on the ixmaps namespace (same convention as userdraw — see Custom Charts). This is a real, shipping example — a CATEGORICAL speed-limit layer where the color depends on the text of each class label, not a fixed palette:
ixmaps.colorScheme_speedmap = function (theme) {
// theme.szLabelA — one label per class, in class order
// theme.colorScheme — mutate in place: one hex string per class
for (var i = 0; i < theme.szLabelA.length; i++) {
if (theme.szLabelA[i].match(/^(45|50|55|60|65|70|75) mph/i)) {
theme.colorScheme[i] = "#CE517F";
} else if (theme.szLabelA[i].match(/^40 mph/i)) {
theme.colorScheme[i] = "#CC6166";
} else if (theme.szLabelA[i].match(/^30/i)) {
theme.colorScheme[i] = "#D0A148";
}
// ... remaining bands, then a fallback for unmatched labels
}
};Load the required helper script and reference the layer as usual:
ixmaps.Map("map_div", { /* ... */ })
.require("../../ui/js/tools/colorscheme.js") // ColorScheme.createColorScheme(), used below
.layer(ixmaps.layer("osm", layer => layer
.data({ type: "ext", name: "OSM_dataquery_stressmap" })
.binding({ position: "geometry", id: "id", value: "maxspeed" })
.type("CHART|FEATURES|CATEGORICAL|LINES")
.style({ colorscheme: "ixmaps.colorScheme_speedmap", linewidth: "3" })
.meta({ title: "Speed limits" })
));iXMaps calls the function once the theme’s classes are resolved (theme.szLabelA populated), then reads theme.colorScheme[i] to paint each class — so this is the way to base color on values the layer only knows after loading (its actual set of categories, quantile breaks, etc.). To start from a named palette and only override specific entries, ColorScheme.createColorScheme(...) (from the same colorscheme.js tool) returns a color array you can index into before selectively overwriting entries — see ixmaps.colorScheme_surfacemap alongside colorScheme_speedmap in the source above for that combined pattern.
colorscheme: "ixmaps.myFunc" works as a bare string (["ixmaps.myFunc"] also works — both are normalized the same way). Never pass an inline function body as the string — the property parser splits on , and |, which corrupts multi-statement source.
A plain JS array built dynamically before the layer is defined works too — colorscheme: buildPalette(n) is just a normal array by the time .style() sees it — but it can’t reflect anything about data this same layer hasn’t loaded yet. Use the function form for anything that depends on the layer’s own resolved classes.
Next steps
- Visualization Types & Modifiers — the full
.type()token reference - Style Properties —
ranges,rangecentervalue,values,nodatacolorand all other color-related style properties