API Reference
Complete reference for the iXMaps JavaScript API.
Map constructor
ixmaps.Map(elementId, options)
Creates a new map instance. Always assign the result to a const — a discarded instance silently breaks all subsequent calls.
const myMap = ixmaps.Map("map", {
mapType: "VT_TONER_LITE",
mode: "info",
legend: "closed",
tools: true
});Parameters:
| Parameter | Type | Description |
|---|---|---|
elementId |
string | ID of the HTML <div> that will contain the map |
options |
object | Map configuration (see below) |
Options:
| Option | Type | Default | Description |
|---|---|---|---|
mapType |
string | "VT_TONER_LITE" |
Basemap style — see Map Types |
mapProjection |
string | (web Mercator) | Projection — "lambert", "equalearth", "orthographic", etc. |
mode |
string | "pan" |
"info" enables tooltips on hover; "pan" pan/zoom only |
legend |
string | "closed" |
"open" or "closed" initial legend panel state |
tools |
boolean | false |
Show the map toolbar (zoom buttons, search) |
projectionParams |
object | — | Albers-only: custom standard parallels / center |
Returns: a MapBuilder instance — chainable.
Map chain methods
The map builder supports a fluent API. Call these methods immediately after ixmaps.Map().
.view(config)
Set the initial center and zoom.
// Standard (Mercator / tile-based):
.view({ center: { lat: 42.5, lng: 12.5 }, zoom: 6 })
// Projection maps (MUST use array form):
.view([42.5, 12.5], 6)| Zoom | Scale | Coverage |
|---|---|---|
| 1–3 | world / continent | |
| 4–6 | country | |
| 7–10 | region / state | |
| 11–14 | city | |
| 15–18 | street / building |
.options(opts)
Configure rendering and behaviour.
.options({
objectscaling: "dynamic", // symbols scale with zoom
normalSizeScale: "8000000", // ⚠️ REQUIRED with objectscaling
basemapopacity: 0.6,
flushChartDraw: 1000000 // 1 000 000 = instant (no animation)
})| Option | Type | Description |
|---|---|---|
objectscaling |
string | "dynamic" — symbols grow/shrink with zoom |
normalSizeScale |
string | Required with objectscaling. Map scale denominator at which charts render at their nominal size. Zoom 6 ≈ "8000000", zoom 12 ≈ "100000" |
dynamicScalePow |
string | Exponent for zoom scaling. "1.8" recommended for dense point sets |
featurescaling |
string | "true" — scale individual features relative to each other |
basemapopacity |
number | Opacity of basemap tiles. 0 = invisible, 1 = fully opaque |
flushChartDraw |
number | Rendering batch size. 1000000 = instant, 1 = animated one-by-one |
flushPaintShape |
number | Set to 1000000 for large polygon datasets (municipalities) to prevent render hangs |
zoomAnimation |
boolean | Smooth zoom transitions. false = snap |
.on(events, handler)
Subscribe to map events. Multiple space-separated event names are accepted.
myMap
.on("ready", () => hideSpinner())
.on("layerdraw", e => console.log("drawn:", e.id))
.on("click", e => showDetail(e.id))
.on("mouseover", e => highlight(e.id))
.on("mouseout", () => clearHighlight())
.on("zoomend moveend", () => updateStats());View events:
| Event | Fires when |
|---|---|
zoomend |
Zoom changed |
moveend |
Map panned |
viewchange / zoompan |
Any zoom or pan |
Item (feature) events: handler receives { szId, id, theme, szMap } where id = item key.
| Event | Fires when |
|---|---|
mouseover / itemover |
Pointer enters a feature |
mouseout / itemout |
Pointer leaves a feature |
click / itemclick |
Feature clicked |
Lifecycle events:
| Event | Fires when |
|---|---|
ready / mapready |
SVG engine fully loaded |
layerdraw / drawtheme |
A layer finishes drawing |
layeradd / newtheme |
A layer is created |
layerremove / removetheme |
A layer is removed |
Layer chain
Every data layer uses the same method chain:
myMap.layer("layerName")
.data({...}) // ① data source
.binding({...}) // ② field mapping ← required
.filter("...") // ③ optional filter
.type("...") // ④ visualization type
.style({...}) // ⑤ style properties
.meta({...}) // ⑥ tooltip / metadata
.title("...") // ⑦ legend label
.define() // ⑧ register (required — must close every chain).data(config) — data source
Inline JSON:
.data({ obj: myArray, type: "json" })
.data({ obj: myArray, type: "json", cache: "true" }) // reuse for multiple layersExternal file:
.data({ url: "https://example.com/data.csv", type: "csv" })
.data({ url: "https://example.com/geo.topojson", type: "topojson" })Supported type values: "json" · "jsonl" · "csv" · "geojson" · "topojson" · "parquet" · "geoparquet" · "geopackage" / "gpck" · "flatgeobuf" / "fgb" · "geobuf" / "pbf"
Multi-source loading (Data.provider):
var loadData = function(themeObj, options) {
Data.provider()
.addSource("https://example.com/2022.csv.gz", "csv")
.addSource("https://example.com/2023.csv.gz", "csv")
.realize(function(dataA) {
dataA[0].append(dataA[1]);
options.type = "dbtable";
ixmaps.setExternalData(dataA[0], options);
});
};
myMap.layer("events")
.data({ name: "themeDataObj", query: loadData.toString(), cache: "true" })
// ...The function passed to query: is serialised with .toString(). It cannot reference outer-scope variables — make everything self-contained inside the function body.
.binding(config) ⚠️ Required
Maps data fields to map properties.
Point data (CSV / JSON with lat/lon columns):
.binding({ geo: "lat|lon", value: "fieldname", title: "label" })
.binding({ geo: "geometry", value: "fieldname", title: "label" }) // GeoJSON Point geometryGeoJSON / TopoJSON with join:
.binding({ geo: "geometry", id: "CNTR_ID", title: "NAME_ENGL" })Choropleth overlay (joins to FEATURE base by id):
.binding({ lookup: "csv_code_col", value: "metric" })
// "lookup" field must match the "id" field of the FEATURE baseMulti-value (sparklines, stacked bars, flows):
.binding({ geo: "lat|lon", value: "val2020|val2021|val2022|val2023" })With size driven by a separate field (categorical color + numeric size):
.binding({ geo: "lat|lon", value: "category", title: "name", size: "numericField" })Time series:
.binding({ geo: "lat|lon", value: "metric", title: "name", timefield: "year" })| Key | Purpose |
|---|---|
geo |
Coordinates: "lat\|lon" for columns, "geometry" for GeoJSON geometry |
id |
Feature identifier for later joins (FEATURE base layers) |
lookup |
Join key on the data side (must match id in the geometry) |
value |
Field(s) to visualise — pipe-separated for multi-value |
title |
Display name in tooltips |
size |
Independent size field when using CATEGORICAL with numeric sizing |
alpha |
Field for dynamic opacity (DOPACITYMAX / DOPACITYMINMAX) |
timefield |
Time field for animated / time-slider maps |
.filter(expression) — optional
Filter rows before visualisation.
.filter('WHERE country == "IT"')
.filter('WHERE year == 2024')
.filter('WHERE value > 100 AND category in (A,B,C)')Use double quotes for string values — single quotes are not string delimiters and produce no matches. Use AND / OR not && / ||.
.type(vizType) — visualization type
The type string is composed by piping modifiers with |. See Map Types, Sizing & Colors for the full reference.
Quick reference:
| Type string | Renders |
|---|---|
"FEATURE" |
Polygon or line boundaries only |
"CHOROPLETH\|QUANTILE" |
Colour-coded polygons joined to a FEATURE base |
"CHART\|DOT" |
Uniform dots at coordinates |
"CHART\|BUBBLE\|SIZE\|VALUES" |
Sized bubbles with value labels |
"CHART\|BUBBLE\|CATEGORICAL" |
Bubbles coloured by category |
"CHART\|PIE" |
Pie charts at coordinates |
"CHART\|BAR\|STACKED" |
Stacked / grouped bar charts |
"CHART\|SYMBOL\|PLOT\|LINES" |
Sparklines (time-series curves) |
"CHART\|VECTOR\|BEZIER\|POINTER" |
Flow arrows |
.style(props) — visual properties
See Style Properties for the complete reference. Minimum required for any layer:
.style({ showdata: "true" }) // ⚠️ required — missing this = nothing renders.meta(config) — tooltip and metadata
.meta({ tooltip: "{{name}}: {{value}}" })
.meta({ name: "myLayer", tooltip: "{{theme.item.chart}}{{theme.item.data}}" })| Key | Purpose |
|---|---|
tooltip |
Mustache template for the hover tooltip |
name |
Theme name — required for changeThemeStyle, hideTheme, showTheme |
Tooltip placeholders:
| Syntax | Result |
|---|---|
{{fieldname}} |
iXMaps-formatted value |
{{raw.fieldname}} |
Raw unformatted value — bypasses all iXMaps formatting |
{{theme.item.chart}} |
Built-in chart SVG for this item |
{{theme.item.data}} |
Built-in data table for this item |
Runtime API
Access the live map instance through myMap.then():
myMap.then(function(api) {
// api is the live iXMaps map object
api.changeThemeStyle("layerName", "filter:WHERE year == 2024", "set");
api.removeTheme("prevTheme");
api.setBasemapOpacity(0.3, "absolute");
});api.changeThemeStyle(name, styleString, mode)
Modify a style property on a live layer and trigger re-render.
myMap.then(api => {
api.changeThemeStyle("cities", "filter:WHERE pop > 500000", "set");
api.changeThemeStyle("cities", "filter", "remove"); // clear filter
api.changeThemeStyle("cities", "scale:1.2", "set");
api.changeThemeStyle("cities", "gridwidthpx:1.1", "factor"); // multiply by 1.1
});| Mode | Effect |
|---|---|
"set" |
Replace the property value |
"remove" |
Delete the property entirely |
"factor" |
Multiply the current numeric value by the given factor |
"set\|silent" |
Set without triggering a redraw |
name in .meta()
changeThemeStyle finds themes by the name key in .meta(). Without it, the call silently has no effect.
api.removeTheme(name)
Remove a layer by its meta.name. Use this before redefining an overlay to prevent stacking:
let ACTIVE = null;
function showYear(year) {
const themeName = "year-" + year;
const prev = ACTIVE;
myMap.then(api => {
if (prev) { try { api.removeTheme(prev); } catch(e) {} }
myMap.layer("countries")
.data({ obj: yearData[year], type: "json" })
.binding({ geo: "lat|lon", value: "metric" })
.type("CHART|BUBBLE|SIZE|VALUES")
.style({ colorscheme: ["#0066cc"], showdata: "true" })
.meta({ name: themeName, tooltip: "{{name}}: {{metric}}" })
.define();
ACTIVE = themeName;
});
}ixmaps.hideTheme(name) / ixmaps.showTheme(name)
Toggle layer visibility by meta.name. For initially hidden layers, use visible: false in .style():
myMap.layer("overlay")
.style({ ..., visible: false })
.meta({ name: "overlay" })
.define();
// Later:
ixmaps.showTheme("overlay");
ixmaps.hideTheme("overlay");
// Checkbox toggle:
// <input type="checkbox" onchange="this.checked ? ixmaps.showTheme('overlay') : ixmaps.hideTheme('overlay')">ixmaps.getZoom() / ixmaps.getCenter()
Global helpers — call directly without .then():
const z = ixmaps.getZoom();
const c = ixmaps.getCenter(); // { lat, lng }api.getBounds()
Returns a flat 4-element array [swLat, swLng, neLat, neLng]:
myMap.then(function(m) {
const bounds = m.getBounds();
if (!bounds || bounds.length !== 4) return;
const [swLat, swLng, neLat, neLng] = bounds;
});Projections
All projections use SVG-based rendering. Omit mapProjection for the default Web Mercator / Leaflet tile setup.
mapProjection |
Alias | Projection |
|---|---|---|
| (omit) | — | Web Mercator (Leaflet tiles) |
"mercator" |
— | Mercator (SVG, no tiles) |
"winkel" |
— | Winkel Tripel |
"equalearth" |
— | Equal Earth |
"albersequalarea" |
"albers" |
Albers Equal-Area Conic |
"lambertazimuthalequalarea" |
"lambert" |
Lambert Azimuthal Equal-Area (EPSG:3035) |
"orthographic" |
— | Orthographic (globe) |
- Lookup is case-insensitive
- For any projection:
.view()must use array syntax.view([lat, lng], zoom) - Set
mapTypeto a hex color ("#0a1929","white","dark") as background — do not use CSSbackgroundon#map
Lambert (Eurostat-style Europe):
const myMap = ixmaps.Map("map", {
mapType: "white",
mapProjection: "lambert",
mode: "info",
legend: "closed",
tools: false
})
.view([53.4, 16.9], 3.7)
.options({ basemapopacity: 0, flushChartDraw: 1000000 });Geometry sources (quick reference)
World countries (GISCO):
.data({ url: "https://gisco-services.ec.europa.eu/distribution/v2/countries/topojson/CNTR_RG_60M_2020_4326.json", type: "topojson" })
.binding({ geo: "geometry", id: "CNTR_ID", title: "NAME_ENGL" })
// Scales: 60M (world) · 20M · 10M · 3M · 1M (country)
// ⚠️ Join field is CNTR_ID, NOT CNTR_CODEItaly municipalities (ISTAT 2024-compatible):
.data({ url: "https://raw.githubusercontent.com/gjrichter/geo/0153a0e14da5dae877b8c94d6deb11f210d4660a/italy/boundaries/italy_istat_municipalities_4326_500m.topojson", type: "topojson" })
.binding({ geo: "geometry", id: "com_istat_code_num", title: "name" })
// com_istat_code_num = integer 28001 (use for joins with ISTAT CSVs)
// com_istat_code = zero-padded string "028001"
// ⚠️ Add flushPaintShape: 1000000 to .options() for all ~8000 polygonsGermany LAU municipalities:
.data({ url: "https://cdn.jsdelivr.net/gh/gjrichter/geo@028b3fe/lau/germany_lau_2021_4326.topojson", type: "topojson" })
.binding({ geo: "geometry", id: "LAU_ID", title: "LAU_NAME" })NUTS1–3 (Eurostat):
.data({ url: "https://gisco-services.ec.europa.eu/distribution/v2/nuts/topojson/NUTS_RG_60M_2021_4326_LEVL_1.json", type: "topojson" })
.binding({ geo: "geometry", id: "NUTS_ID", title: "NUTS_NAME" })
// For a single country: .filter('WHERE CNTR_CODE == "DE"')