This is the documentation of version 1.0.0-rc.3. Go to the latest version, 1.0.0-rc.5.

Geometries module

GeometriesModule draws polygons on the map, each with a fill, a border and a label. They can be administrative boundaries from the geometry data service, or any GeoJSON Polygon and MultiPolygon features of your own.

Showing geometries

Initializing geometry module

import { TomTomConfig } from '@tomtom-org/maps-sdk/core';
import { TomTomMap, GeometriesModule } from '@tomtom-org/maps-sdk/map';

TomTomConfig.instance.put({ apiKey: 'YOUR_API_KEY' });
const map = new TomTomMap({ mapLibre: { container: 'map' } });

const geometryModule = await GeometriesModule.create(map);

Displaying administrative boundaries

import { geocode, geometryData } from '@tomtom-org/maps-sdk/services';

const place = (await geocode({ query: 'Amsterdam, Netherlands' })).features[0];
const geometryResponse = await geometryData({ geometries: [place] });

await geometryModule.show(geometryResponse);

show replaces the geometries shown, and clear removes them.

Your own polygons go to show the same way. These delivery zones are hand-drawn GeoJSON, each with its own colour, label and clicked look:

Custom styling configuration

One top-level color sets the fill and the border together:

const geometryModule = await GeometriesModule.create(map, { color: '#E63312' });

The colours resolve in this order, and the first match wins:

Part Precedence
Fill a feature's own color property → fill.color → fill.palette → color → the map's accent → the default
Border line.color → a feature's own color property → fill.color → fill.palette → color → the map's accent → the default

fill and line configure the fill and the border separately. The fill takes fill: { color, opacity }, or a palette instead of one colour. The border takes line: { color, width, opacity, pattern }. Set pattern from 'solid' to 'dashed' or 'dotted' to break the border up. The dashes and dots scale with its width.

const geometryModule = await GeometriesModule.create(map, {
    fill: { color: '#007cbf', opacity: 0.3 },
    line: { color: '#005a8b', width: 2, opacity: 0.8, pattern: 'dashed' },
    beforeLayerConfig: 'lowestLabel' // below all the map's labels
});

For anything else, layers takes a partial MapLibre layer, without id or source, for each of the module's layers: fill, line (the border), label (the center labels) and lineLabel (the border labels). An entry can set any property of its layer. Its paint and layout merge per property onto the module's own and override the curated fields:

const geometryModule = await GeometriesModule.create(map, {
    line: { color: '#00A65E', width: 2 },
    layers: {
        line: {
            paint: {
                'line-offset': 2,          // inset/outset border, in pixels
                'line-blur': 4,            // glow, in pixels
                'line-gap-width': 3        // hollow casing
            },
            layout: { 'line-cap': 'round' }
        },
        label: { layout: { 'text-transform': 'uppercase' } }
    }
});

Restyling shown geometries

A config change to the colours, fill style, labels or transformFeaturesForDisplay updates the geometries on the map without a new show(). applyConfig replaces the whole config, updateConfig changes only what you pass, and resetConfig restores the defaults:

await geometryModule.show(cityBoundaries);

geometryModule.updateConfig({ fill: { style: 'outline', palette: ['#e63312', '#f5a000'] } });
geometryModule.updateConfig({ label: { title: ['get', 'name'] } }); // keeps the palette and fill style
geometryModule.resetConfig(); // default colours, fill style and labels

getConfig() returns the settings to store. All of it survives JSON except the transformFeaturesForDisplay function. GeometriesModuleSerializableConfig types what you parse back, and you add the function in code:

import type { GeometriesModuleSerializableConfig } from '@tomtom-org/maps-sdk/map';

const saved: GeometriesModuleSerializableConfig = JSON.parse(JSON.stringify(geometryModule.getConfig()));
geometryModule.applyConfig({ ...saved, transformFeaturesForDisplay: addAreaLabels });

Hovered and clicked geometries

Once a handler covers the geometries, a hovered or clicked geometry draws a denser fill and a wider border in its own colour. The module's event state methods set that state from your own UI:

geometryModule.events.on('click', (geometry) => console.log(geometry.properties.name));
geometryModule.setEventState({ index: 0, state: 'click' });

An id is the properties.id that getShown() and the handlers return. The module generates one for a feature that has none, so a geometry data result's top-level id matches nothing.

highlight sets how much denser the fill gets and how much wider the border. Try it in the geometry config playground:

geometryModule.applyConfig({
    fill: { opacity: 0.3 },
    highlight: { fill: { opacityFactor: 3 }, line: { widthFactor: 1 } }, // 0.9 while hovered, the border as is
});

Events

events covers the geometries and all their labels, and a handler receives the feature as drawn. Two named scopes each cover one surface, with the same handlers and event states. events.geometry covers the fills, borders and border labels, and events.geometryLabel covers the center labels.

geometryModule.events.on('click', (geometry, lngLat) => console.log(geometry.properties.title, lngLat));
geometryModule.events.geometry.on('hover', (geometry) => showTooltip(geometry.properties.title));

The user events guide covers the event types and their timings.

Showing and hiding

setVisible hides and shows the fills, borders, center labels and border labels together. To start the module hidden, pass visible: false at creation. show() and clear() never change visibility, so geometries shown while hidden appear on setVisible(true). The state survives a style change.

function toggleGeometry() {
    geometryModule.setVisible(!geometryModule.isVisible());
}

Layer positioning and styling

A single beforeLayerConfig positions all geometry layers together. The record form { all?, fill?, line? } places the fill and the border separately:

const geometryModule = await GeometriesModule.create(map, {
    fill: { color: '#87CEEB', opacity: 0.5 },
    line: { color: '#4682B4', width: 1.5 },
    // Fill slips below the road network, the border below the map's labels
    beforeLayerConfig: { fill: 'lowestRoadLine', line: 'lowestLabel' }
});

Labels

Each polygon whose feature has a title property gets a center label, which label styles. lineLabel repeats it along the border, but only when you set it. Pass {} for the defaults.

const module = await GeometriesModule.create(map, {
    label: { title: ['get', 'name'], size: 18, color: '#FFFFFF', haloColor: '#000000' },
    lineLabel: { title: ['get', 'name'], minZoom: 10, size: 13, offset: [0, 1], symbolSpacing: 350 },
});

// Later: restyle the center labels of the shown geometries, keeping their other settings
module.updateConfig({ label: { ...module.getConfig()?.label, size: 20 } });

Deriving display properties

transformFeaturesForDisplay receives what you passed to show() and returns the features to draw, so a label or a colour can come from your own domain data. It runs on every show(), and again whenever a config change alters what is drawn:

const module = await GeometriesModule.create(map, {
    transformFeaturesForDisplay: (geometries) => ({
        ...geometries,
        features: geometries.features.map((feature) => ({
            ...feature,
            properties: { ...feature.properties, title: `${feature.properties?.name} (${feature.properties?.population})` },
        })),
    }),
});

Fill styles

Fill style Effect
'filled' Semi-transparent fill (default)
'outline' Transparent fill with a thick border
'inverted' Semi-transparent area outside the polygon

Setting the fill style at config level

fill.style applies one fill style to every feature, and a feature's own fillStyle property overrides it:

import { GeometriesModule } from '@tomtom-org/maps-sdk/map';

// Highlight "rest of the world" outside a country
const module = await GeometriesModule.create(map, {
    fill: { style: 'inverted', color: 'black', opacity: 0.5 },
});
await module.show(countryGeometry);

Using fillStyledGeometryConfig for mixed fill styles

For features in one module with different fill styles, fillStyledGeometryConfig({ palette?, beforeLayerConfig? }) returns a config whose expressions read each feature's fillStyle property. beforeLayerConfig defaults to 'lowestLabel', and the config draws the border labels too.

import { GeometriesModule, fillStyledGeometryConfig } from '@tomtom-org/maps-sdk/map';

const module = await GeometriesModule.create(map, fillStyledGeometryConfig({ palette: ['#0077b6', '#90e0ef'] }));

await module.show({
    type: 'FeatureCollection',
    features: [
        { ...featureA, properties: { fillStyle: 'filled', title: 'Zone A' } },
        { ...featureB, properties: { fillStyle: 'outline', title: 'Zone B' } },
    ],
});

Color palettes

fill.palette is a list of CSS colours that the features take in turn, starting over after the last, so neighbouring polygons stay distinct without a colour assigned to each.

import { fillStyledGeometryConfig, GeometriesModule } from '@tomtom-org/maps-sdk/map';
import { deriveMapColors } from '@tomtom-org/maps-sdk-plugin-map-theme';

const regions = await GeometriesModule.create(map, {
    fill: { palette: ['#ffadad', '#ffd6a5', '#caffbf', '#a0c4ff'], opacity: 0.3 },
});

// fillStyledGeometryConfig takes it as its `palette` option
const { accent, water, roadMajor } = deriveMapColors(['#1d3f8a', '#e63312', '#f5d000', '#f4f1ea']);
const zones = await GeometriesModule.create(map, fillStyledGeometryConfig({ palette: [accent, water, roadMajor] }));

To shade the features in order instead, set fill.paletteMode from 'cycle' to 'ramp'. The features then blend evenly from the palette's first colour to its last, so two colours cover any number of features. The blend runs in the OKLCH colour space, which keeps the steps between two colours as vivid as the colours themselves.

const districts = await GeometriesModule.create(map, {
    fill: { palette: ['#f5d000', '#6a1b9a'], paletteMode: 'ramp', opacity: 0.6 },
});

Reachable ranges have their own reachable ranges module. It titles each band from its budget, nests each origin's bands and colours them from the map.

Every setting as data

geometriesKnobCatalogue lists every plain-valued display setting of the module with its kind, its range or options, and its default where one value holds everywhere. Each id is the setting's path in the config, so a UI can build its controls from it with no map loaded:

import { geometriesKnobCatalogue } from '@tomtom-org/maps-sdk/map';

const borderKnobs = geometriesKnobCatalogue.filter(({ id }) => id.startsWith('line.'));
// [{ id: 'line.color', kind: 'color', description: '…' }, …,
//  { id: 'line.width', kind: 'number', description: '…', range: { min: 0, max: 20, step: 0.5, bounds: 'hard-min' } }]
Id Kind
color, visible colour, toggle
fill.style, fill.color, fill.palette, fill.paletteMode, fill.opacity enum, colour, colours, enum, number
line.color, line.opacity, line.width, line.pattern colour, number, number, enum
highlight.fill.opacityFactor, highlight.line.widthFactor factor, 1 to 4 and 1 to 3
label.size, label.color, label.haloColor, label.haloWidth, label.opacity, label.font, label.typeface number, colour, colour, number, number, enums, enum
lineLabel.size, lineLabel.color, lineLabel.haloColor, lineLabel.haloWidth, lineLabel.opacity, lineLabel.font, lineLabel.typeface, lineLabel.minZoom, lineLabel.symbolSpacing, lineLabel.offset the label knobs, then number, number, offset

Multiple module instances

Each instance has its own sources, layers and configuration, so several can show different sets of geometries side by side:

const countryBorders = await GeometriesModule.create(map, {
    fill: { color: '#E74C3C', opacity: 0.2 },
    line: { color: '#C0392B', width: 3 }
});

const cityBounds = await GeometriesModule.create(map, {
    fill: { color: '#3498DB', opacity: 0.3 },
    line: { color: '#2980B9', width: 2 }
});

await countryBorders.show(countryData);
await cityBounds.show(cityData);

Reading shown data

getShown() returns what the module draws, as prepared for display:

const { geometry } = geometryModule.getShown();
console.log(`Geometries: ${geometry.features.length}`);

Related guides and examples

Services integration

Related examples

Related map modules