Integration Documentation

Everything you need to integrate Kartograf.

From basic setup to custom plugin development. Covers the complete declarative Story API with feature config references and examples.

01

Introduction

Kartograf is a geospatial animation and storytelling library built on MapLibre GL JS. It extends standard GeoJSON with custom geometry types — such as animated line-point paths, bezier arcs, and time-series timelines.

It exposes a clean declarative Story API (createStoryplay). Define scenes with camera settings, GeoJSON features, and transition delays — Kartograf normalizes the config into its internal rendering pipeline automatically.

Kartograf exposes a clean declarative Story API (createStoryplay). Define scenes with camera settings, GeoJSON features, and transition delays — Kartograf normalizes the config into its internal rendering pipeline automatically.

02

Installation

npm install kartograf

Kartograf requires MapLibre GL JS as a peer dependency:

npm install maplibre-gl

Peer dependencies (installed automatically):

03

Basic Setup

Initialize a MapLibre map, then create a Kartograf instance bound to it:

import Kartograf from 'kartograf';
import maplibregl from 'maplibre-gl';

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json',
  center: [35, 39],
  zoom: 5,
});

map.on('load', () => {
  const kartograf = new Kartograf({
    mapInstance: map,
  });

  // Ready to load data
});

The constructor takes a single options object:

OptionTypeRequiredDescription
mapInstancemaplibregl.MapYesMapLibre GL map instance with loaded style
libraryRefanyNoOptional external library reference for custom rendering

Scene Transitions

Transitions are configured at the scene level via transition:

FieldTypeDefaultDescription
transition.delaynumber0Seconds to wait after the scene finishes before advancing to the next scene
04

Feature Properties

Features in a scene use a clean shorthand syntax. Kartograf normalizes this into the internal format automatically.

Scene Configuration

FieldTypeRequiredDescription
idstringNoScene identifier (used for branching)
cameraobjectNoCamera behavior for this scene's features
featuresarrayYesArray of features (declarative or GeoJSON)
transitionobjectNo{ delay: number } — seconds after scene ends
metaobjectNo{ audioUrl: string } — narration file

StoryPlayer

Created by kartograf.createStory(config). Manages playback.

MethodReturnsDescription
play()PromisePlay the story from the first scene. Resolves when all scenes complete.
stop()voidStop playback immediately.
getProgress()number0–1 progress ratio.
getCurrentScene()Scene|nullCurrently playing scene.

Events on the Story

Attach listeners via story.story.on(event, handler):

story.story.on('sceneStart', (scene) => { /* ... */ });
story.story.on('sceneEnd', (scene) => { /* ... */ });
story.story.on('complete', () => { /* ... */ });
06

Geometry Types

Kartograf supports 21 geometry types: 7 standard GeoJSON and 14 custom patch types. The factory routes each type to the appropriate Layer class.

Point

Standard

Single location with itemDisplayImage configuration. Supports CIRCLE, PULSING_ANIMATED, STABLE_ANIMATED, and THREED display modes. Camera flies to the point coordinates.

{
  geometry: { type: 'Point', coordinates: [28.978, 41.008] },
  marker: { type: 'PULSING', popup: { title: 'Istanbul' } },
}

LineString

Standard

Path with optional progressive draw animation. Camera fits bounds to the line with configurable buffer.

{
  geometry: {
    type: 'LineString',
    coordinates: [[28.978, 41.008], [32.860, 39.933]],
  },
  line: { color: '#c9a87c', width: 3, animate: true },
}

Polygon

Standard

Filled area with semi-transparent red fill. Camera fits to bounds. No marker or line config — display is purely geometric.

{
  geometry: {
    type: 'Polygon',
    coordinates: [[[32.8, 39.8], [32.9, 39.9], [32.7, 39.9], [32.8, 39.8]]],
  },
}

MultiPoint

Standard

Multiple points, each with independent marker configuration. The markers array maps 1:1 to coordinates by position. Each point can have a different display type and popup. Supports 3D models per point.

{
  geometry: {
    type: 'MultiPoint',
    coordinates: [
      [28.978, 41.008],
      [32.860, 39.933],
    ],
  },
  markers: [
    { type: 'PULSING', popup: { title: 'Istanbul' } },
    { type: 'CIRCLE' },
  ],
}

MultiLineString

Standard

Multiple lines, each with independent styling via the lines array. Each line can have different color, width, animate settings. Animates all lines simultaneously in lockstep.

{
  geometry: {
    type: 'MultiLineString',
    coordinates: [
      [[28.978, 41.008], [30.520, 39.800]],
      [[32.860, 39.933], [27.138, 38.423]],
    ],
  },
  lines: [
    { color: '#c9a87c', width: 3, animate: true },
    { color: '#88c0d0', width: 2, animate: true },
  ],
}

MultiPolygon

Standard

Multiple polygons rendered as fills. Each polygon is drawn with a semi-transparent red fill. No per-polygon styling — all share the same paint properties.

{
  geometry: {
    type: 'MultiPolygon',
    coordinates: [
      [[[32.8, 39.8], [32.9, 39.9], [32.7, 39.9], [32.8, 39.8]]],
      [[[33.0, 40.0], [33.2, 40.2], [33.0, 40.0]]],
    ],
  },
}

LinePointString Custom

The signature Kartograf type. A LineString that draws progressively while a point marker moves along the path tip simultaneously. Internally, this is a cross-breed — the geometry type is LinePointString, which the parser converts to LineString with itemType: "LinePointString". The factory then routes it to LinePointLayer instead of LineLayer.

Both marker and line configs are applied. The point can be a pulsing dot, static marker, or THREED 3D model. The line can have its own styling independent of the point.

{
  geometry: {
    type: 'LinePointString',
    coordinates: [[28.978, 41.008], [30.520, 39.800], [32.860, 39.933],
  },
  marker: { type: 'PULSING', popup: { title: 'Traveler' } },
  line: { color: '#c9a87c', width: 3, animate: true },
}

MultiLinePointString Custom

Multiple lines with simultaneous point animation. Each line draws while its corresponding point moves along the path tip. Uses both markers and lines arrays. The point markers update their positions frame by frame, and 3D models move in real-time.

{
  geometry: {
    type: 'MultiLinePointString',
    coordinates: [
      [[28.978, 41.008], [30.520, 39.800]],
      [[32.860, 39.933], [27.138, 38.423]],
    ],
  },
  markers: [
    { type: 'PULSING', popup: { title: 'Convoy A' } },
    { type: 'CIRCLE' },
  ],
  lines: [
    { color: '#c9a87c', width: 3, animate: true },
    { color: '#88c0d0', width: 2, animate: true },
  ],
}

LineArc Custom

Takes exactly two coordinates (start and end) and generates a smooth quadratic bezier curve between them using Turf.js. The arc's control point is calculated as a perpendicular offset from the midpoint. Internally, the parser converts LineArc to LineString with computed bezier coordinates and routes it to LineLayer — there is no dedicated LineArcLayer.

{
  geometry: {
    type: 'LineArc',
    coordinates: [[28.978, 41.008], [51.390, 35.689]],
  },
  line: { color: '#88c0d0', width: 3, animate: true },
}

Algorithm: turf.midpoint(start, end) → perpendicular offset by distance/4turf.bezierSpline([start, control, end]) → resulting bezier coordinates.

MultiLineArc Custom

Multiple arc pairs. Each pair [start, end] is independently converted to a bezier curve. The result is rendered as a MultiLineString and routed to MultiLineLayer — there is no dedicated MultiLineArcLayer.

{
  geometry: {
    type: 'MultiLineArc',
    coordinates: [
      [[28.978, 41.008], [32.860, 39.933]],
      [[27.138, 38.423], [30.520, 39.800]],
    ],
  },
  lines: [
    { color: '#c9a87c', width: 3, animate: true },
    { color: '#88c0d0', width: 2, animate: true },
  ],
}

Timeline Custom

Time-series data visualization within a bounding polygon. Fetches external GeoJSON data and iterates through date or numeric values, rendering points frame by frame. The initialQuery is used for the first frame; subsequent frames use query with CURRV and PREVV keywords substituted at runtime.

{
  geometry: {
    type: 'Timeline',
    coordinates: [[[26, 42], [45, 42], [45, 35], [26, 35], [26, 42]]],
  },
  timeline: {
    url: 'https://api.example.com/events.geojson',
    start: '1200-01-01',
    end: '1453-05-29',
    step: 30,
    qualifier: 'DATE',
    fps: 120,
    paint: { color: '#c9a87c', radius: 5, opacity: 0.7 },
    initialQuery: "['all',['==','$type','Point'],['==','date',CURRV]]",
    query: "['all',['==','$type','Point'],['>=','date',PREVV],['<','date',CURRV]]",
  },
}

Reserved keywords for queries:

KeywordReplaced With
CURRVCurrent iteration value (date or number)
PREVVPrevious iteration value

GeometryCollection Custom

Mixed geometry types in a single feature. Supports sequential display with per-sub-geometry display configs inlined directly in each geometry object. The destructGeometryCollection function destructures the GC into individual Feature objects, propagating parent properties to each sub-feature with itemLocalIndex for filtering.

Key behaviors:

{
  geometry: {
    type: 'GeometryCollection',
    geometries: [
      {
        type: 'Point',
        coordinates: [28.978, 41.008],
        // Inline config for this sub-geometry:
        marker: { type: 'PULSING', popup: { title: 'Start' } },
      },
      {
        type: 'LineString',
        coordinates: [[28.978, 41.008], [32.860, 39.933]],
        line: { color: '#c9a87c', width: 3, animate: true },
      },
      {
        type: 'LinePointString',
        coordinates: [[32.860, 39.933], [27.138, 38.423]],
        marker: { type: 'CIRCLE' },
        line: { color: '#8fbcbb', width: 2, animate: true },
      },
    ],
  },
  sequence: true,
  delayDurationInSecond: 2,
  focusedItemIndexes: [0, 2],
}

Circle New

Custom

Generates a polygon approximation of a circle from a center point and radius using Turf.js. Supports sweep, pulse, and breathe animations.

{
  geometry: { type: 'Circle', coordinates: [28.978, 41.008] },
  circle: { radius: 50, unit: 'km', color: '#c9a87c', opacity: 0.4, animate: 'sweep', speed: 1 },
}

Extrusion New

Custom

3D polygon extrusion using MapLibre's fill-extrusion paint type. Supports rise (grow height), wave (oscillate), and color sweep animations.

{
  geometry: { type: 'Extrusion', coordinates: [[[bounds...]]] },
  extrusion: { height: 200, color: '#c9a87c', opacity: 0.7, base: 0, animate: 'rise', speed: 1 },
}

Donut New

Custom

Two concentric circles producing a ring polygon with a hole. Supports sweep (inner radius grows) and pulse (thickness oscillates) animations.

{
  geometry: { type: 'Donut', coordinates: [28.978, 41.008] },
  donut: { innerRadius: 10, outerRadius: 50, unit: 'km', color: '#c9a87c', opacity: 0.5, animate: 'sweep', speed: 1 },
}

FlowLine New

Custom

Line with animated particles flowing continuously along the path. Two modes: particles (flowing dots) and stream (moving dash pattern). Supports glow and progressive draw animation before the flow begins.

{
  geometry: { type: 'FlowLine', coordinates: [[lng, lat], ...] },
  flow: {
    type: 'particles',
    color: '#c9a87c',
    width: 3,
    particleCount: 20,
    speed: 0.5,
    size: 4,
    animationDuration: 3000,
    glow: { color: '#c9a87c', width: 8, opacity: 0.3, blur: 4 },
  },
}

Cluster New

Custom

MapLibre-native point clustering with automatic cluster counts. Supports explode animation for interactive pulsing cluster/point radii.

{
  geometry: { type: 'Cluster', coordinates: [[lng, lat], ...] },
  cluster: { radius: 50, maxZoom: 14, color: '#c9a87c', animate: 'explode', speed: 1 },
}

IconPoint New

Custom

Image-based point marker using an external image URL. The image is rendered inside a CSS shape mask — choose square, circle, or octagon. Supports optional border. Uses an HTML marker element instead of a MapLibre symbol layer for full CSS control.

Note: Standalone IconPoint does not support popups or bounce animation. To use an image marker with a popup, set marker: { type: "ICON_POINT", iconPointConfig: { ... } } on a Point or LinePointString instead.
{
  geometry: { type: 'IconPoint', coordinates: [28.978, 41.008] },
  iconPoint: {
    imageUrl: 'https://example.com/icon.jpg',
    shape: 'circle',
    size: 48,
    border: { color: '#ffffff', width: 2 },
  },
}

Heatmap New

Custom

Density heatmap from point data using MapLibre's native heatmap layer type. Configurable radius, intensity, weight, and color stops. Supports pulse animation that oscillates intensity.

{
  geometry: { type: 'Heatmap', coordinates: [[lng, lat], ...] },
  heatmap: {
    radius: 30,
    intensity: 0.6,
    weight: 1,
    colorStops: [
      [0, 'rgba(33,102,172,0)'],
      [1, 'rgb(178,24,43)']
    ],
    animate: 'pulse',
  },
}

Arc New

Custom

Great-circle curved line between two coordinates using @turf/greatCircle. Renders a smooth flight-path arc. Supports sweep animation (line grows from origin to destination) and optional particles flowing along the arc.

{
  geometry: { type: 'Arc', coordinates: [[28.978, 41.008], [51.390, 35.689]] },
  arc: {
    color: '#88c0d0',
    width: 3,
    npoints: 100,
    animate: 'sweep',
    particles: true,
    particleCount: 15,
  },
}

Label New

Custom

Text label placed on the map via MapLibre's symbol layer with text-field. Configurable font, size, color, halo, offset, and anchor. Works on Point geometry.

{
  geometry: { type: 'Label', coordinates: [28.978, 41.008] },
  label: {
    text: 'Istanbul',
    size: 18,
    color: '#c9a87c',
    haloColor: '#111d2b',
    haloWidth: 2,
  },
}
07

Feature Config Reference

Detailed reference for all declarative configuration fields. These are the clean-format keys that the normalizer maps to internal GeoJSON properties.

Marker

Controls how point-based geometries appear. Used by Point, LinePointString, and as entries in the markers array.

FieldTypeDefaultDescription
typestring"PULSING"PULSING, STABLE, CIRCLE, THREED, ICON_POINT
popup.titlestringPopup header
popup.contentstringPopup body
popup.imagestringPopup background image URL
popup.sizenumberPopup image container size in px
model.urlstringGLTF model URL (requires type: "THREED")
model.sizenumber1Model scale factor
model.anglenumber0Initial rotation in degrees
bouncebooleanfalseAnimate the marker bouncing up and down (currently disabled in code)
iconPointConfigobjectWhen type: "ICON_POINT", pass { imageUrl, shape, size, border }

Display type mapping: PULSINGPULSING_ANIMATED, STABLESTABLE_ANIMATED, CIRCLECIRCLE, THREEDTHREED, ICON_POINTICON_POINT.

Line

Controls how line-based geometries render and animate. Used by LineString, LineArc, LinePointString, and as entries in lines.

FieldTypeDefaultDescription
colorstring"#0f115e"Hex color
widthnumber3Stroke width in pixels
opacitynumber1Stroke opacity (0–1)
blurnumber0Gaussian blur radius
animatebooleantrueProgressive line draw animation
durationnumber3000Animation duration in milliseconds (time-based, independent of line length)
dashedbooleanfalseEnable dashed stroke
dashArraynumber[][2, 2]Dash pattern [on, off]
ghostbooleanfalseShow a dashed preview line ahead of the drawing animation
ghostColorstring"#ffffff"Color of the ghost path line
ghostWidthnumber2Width of the ghost path line
particlesobjectParticle flow config: { count: 15, speed: 0.5, size: 3, color: '#c9a87c' }
glowobjectGlow trail behind the line: { width: 3, color: '#c9a87c', opacity: 0.3, blur: 3 }

FlowLine

Controls the FlowLine layer behavior. Used by FlowLine geometry type.

FieldTypeDefaultDescription
typestring"particles"particles (flowing dots) or stream (moving dash pattern)
colorstring"#c9a87c"Line and particle color
widthnumber3Line width in pixels
sizenumber4Particle radius in pixels
particleCountnumber20Number of flowing particles
speednumber0.5Animation speed multiplier
animationDurationnumber3000Progressive draw duration in ms before flow begins
glowobjectGlow behind the line: { width: 8, color, opacity: 0.3, blur: 4 }

IconPoint Config

Controls the image-based point marker.

FieldTypeDefaultDescription
imageUrlstringURL of the image to display
shapestring"circle"circle, square, or octagon
sizenumber32Marker size in pixels
border.colorstring"transparent"Border color
border.widthnumber0Border width in pixels

Note: The bounce property is documented but not currently implemented for standalone IconPoint or marker-based ICON_POINT.

Heatmap Config

Controls the Heatmap layer behavior.

FieldTypeDefaultDescription
radiusnumber30Heatmap blur radius in pixels
intensitynumber0.5Heatmap intensity multiplier (0–1)
weightnumber1Per-point weight for density
opacitynumber0.8Heatmap opacity
colorStopsarrayArray of [stop, color] pairs for heatmap gradient
animatestringpulse — oscillate intensity
speednumber1Animation speed multiplier

Arc Config

Controls the Arc layer behavior.

FieldTypeDefaultDescription
colorstring"#c9a87c"Arc line color
widthnumber2Arc line width
opacitynumber0.8Arc line opacity
npointsnumber100Number of points on the great-circle arc
animatestringsweep — grow arc from origin
speednumber1Animation speed multiplier
particlesbooleanfalseEnable particle flow after sweep
particleCountnumber15Number of flowing particles
sizenumber3Particle size in pixels

Label Config

Controls the text label layer.

FieldTypeDefaultDescription
textstringLabel text content
colorstring"#333333"Text color
sizenumber12Font size in pixels
opacitynumber1Text opacity
fontarray["Open Sans Regular","Arial Unicode MS Regular"]Font family stack
haloColorstring"#ffffff"Text halo/outline color
haloWidthnumber1Text halo width
offsetarray[0, 0]Text offset [x, y] in ems
anchorstring"center"Text anchor: center, left, right, etc.

Polygon

Controls polygon-specific display and animation behaviors.

FieldTypeDefaultDescription
breathebooleanfalseOscillate fill opacity between 0.2 and 0.8
progressiveFillbooleanfalseGrow polygon from centroid to full size
speednumber1Animation speed multiplier

Circle

Controls the Circle layer behavior. Used by Circle geometry type.

FieldTypeDefaultDescription
radiusnumber50Circle radius
unitstring"kilometers"Radius unit (kilometers, miles, etc.)
colorstring"#c9a87c"Fill color
opacitynumber0.4Fill opacity
animatestringsweep, pulse, breathe
speednumber1Animation speed multiplier

Extrusion

Controls the Extrusion layer behavior. Used by Extrusion geometry type.

FieldTypeDefaultDescription
heightnumber200Extrusion height in meters
colorstring"#c9a87c"Extrusion color
opacitynumber0.7Extrusion opacity
basenumber0Base height in meters
animatestringrise, wave, color
speednumber1Animation speed multiplier

Donut

Controls the Donut layer behavior. Used by Donut geometry type.

FieldTypeDefaultDescription
innerRadiusnumber10Inner ring radius
outerRadiusnumber50Outer ring radius
unitstring"kilometers"Radius unit
colorstring"#c9a87c"Fill color
opacitynumber0.5Fill opacity
animatestringsweep, pulse, breathe
speednumber1Animation speed multiplier

Cluster

Controls the Cluster layer behavior. Used by Cluster geometry type.

FieldTypeDefaultDescription
radiusnumber50Cluster radius in pixels
maxZoomnumber14Maximum zoom level for clustering
colorstring"#c9a87c"Cluster color
animatestringexplode
speednumber1Animation speed multiplier

Buffer

Controls camera bounds padding. Higher values = more zoomed out. A buffer of 25 km is applied if not specified. The buffer is computed using @turf/buffer and the resulting bounding box is passed to map.fitBounds.

DeclarativeInternalDescription
buffer: 15itemBufferSize: [{ index: 0, buffer: 15 }]Buffer in kilometers

Timeline Config

DeclarativeInternalDescription
urlurlGeoJSON endpoint URL
startstartValueStart date "2024-01-01" or number 0
endendValueEnd date or number
stepstepSizeIncrement per frame (days for DATE, number for NUMBER)
qualifierqualifier"DATE" or "NUMBER"
displayTypedisplayType"CIRCLE" or "ANIMATED_POINT"
fpsfpsFrame rate in ms (lower = faster)
paintpaintStyle: { color, radius, opacity }
initialQueryinitialQueryFilter for the first frame
queryqueryFilter for subsequent frames. Keywords: CURRV, PREVV

Image Overlay

Raster image overlaid on the map with 0.7 opacity. Four-corner coordinate system (top-left, top-right, bottom-right, bottom-left).

DeclarativeInternalDescription
overlay.urlmapOverlayImage[].imageUrlImage URL
overlay.coordinatesmapOverlayImage[].coordinatesFour-corner lon/lat array
{
  geometry: { type: 'Polygon', coordinates: [bounds] },
  overlay: {
    url: 'https://example.com/map.jpg',
    coordinates: [
      [29.03, 42.92],
      [50.01, 42.92],
      [50.01, 33.01],
      [29.03, 33.01],
    ],
  },
}

Video Overlay

Video overlaid on the map using four-corner coordinate bounding. Supports autoplay, looping, fade-in/fade-out, and seeking.

DeclarativeInternalDescription
overlay.typetypeSet to "video" for video overlay
overlay.urlimageUrlVideo URL (MP4/WebM)
overlay.coordinatescoordinatesFour-corner lon/lat array
overlay.mutedmutedStart muted
overlay.looploopLoop playback
overlay.playplayAutoplay on add
overlay.fadeInfadeInFade-in duration in ms
overlay.fadeOutfadeOutFade-out duration in ms
overlay.seekseekInitial seek time in seconds
overlay.durationdurationMaximum playback duration in ms
{
  geometry: { type: 'Polygon', coordinates: [bounds] },
  overlay: {
    type: 'video',
    url: 'https://example.com/video.mp4',
    coordinates: [
      [29.03, 42.92],
      [50.01, 42.92],
      [50.01, 33.01],
      [29.03, 33.01],
    ],
    muted: true,
    loop: true,
    play: true,
    fadeIn: 500,
  },
}

Camera Options

Camera is configured at the scene level via scene.camera. Unlike the imperative API, camera does not live inside feature properties — it is a scene-level concern. (The normalizer preserves any cameraOptions if you pass the old format.)

FieldTypeDefaultDescription
zoomLevelnumbermap defaultTarget zoom level
pitchnumber0Camera pitch (0–60)
bearingnumber0Camera rotation (0–360)
shouldRotatebooleanfalseEnable continuous map rotation (0.1° per 10ms)
orbitboolean / numberfalseAuto-orbit camera around the scene center. true = 30s full rotation, or specify seconds: orbit: 60.

GeometryCollection-only camera options:

FieldTypeDefaultDescription
shouldShowInSequencebooleantrueIf false, the sub-geometry renders but the camera does not move.
focusedItemIndexesnumber[]Array of sub-item indexes that trigger camera movement. Others render silently.
delayDurationInSecondnumber0Seconds to wait before advancing to the next sub-item in a sequence.

Camera behavior per geometry:

08

Branching

Stories can have non-linear paths. Branches are evaluated when a scene ends. If the condition passes, playback jumps to the target scene instead of continuing sequentially.

MethodArgumentsDescription
story.story.addBranch(fromId, condition, toId)string, Function|Object, stringAdd a branch rule. condition can be a function (sceneData) → boolean or an object { key, value } for property matching.
// Condition as function
story.story.addBranch(
  'crossroads',
  (sceneData) => sceneData.sceneIndex === 0,
  'northern_route'
);

// Condition as key-value match
story.story.addBranch(
  'northern_route',
  { key: 'completed', value: true },
  'finale'
);
09

Plugin System

Extend Kartograf with custom geometry types by implementing the Layer interface and registering it:

import { Layer } from 'kartograf';

class HeatmapLayer extends Layer {
  // Called to add sources and layers to the map
  add() {
    const { map, element, index, state, camera } = this;
    // Camera is handled automatically by the caller
  }

  // Called to clean up
  remove() {
    // Remove sources, layers, markers
  }

  // Optional: per-frame animation
  animate() {
    // Return when animation is complete
  }
}

kartograf.registerLayerType('Heatmap', HeatmapLayer);

After registration, use the type name in your geometry:

{
  geometry: { type: 'Heatmap', coordinates: [...] },
  // Your custom config fields
}

Layer class interface:

MethodRequiredDescription
constructor(map, element, index, state, camera)Called by the factory. Store references.
add()YesAdd sources, layers, markers. Camera is handled before this is called.
remove()YesRemove all sources and layers this layer added.
animate()NoStart any animation. Fire ITEM_ANIMATION_FINISHED when done.
10

Events Reference

Kartograf fires custom events on the map instance. Listen to them to synchronize external UI, control navigation, or track state.

Event NameSourceFired When
ITEM_IN_ANIMATIONmapA feature animation starts (line draw, point move, camera flight). Sets state.isMapFlyToInProgress = true.
ITEM_ANIMATION_FINISHEDmapAnimation completes. Fires state.mapIsReadyForNextItemDraw() which advances the SequenceRunner.
map.on('ITEM_IN_ANIMATION', () => {
  // Disable UI, show loading
});

map.on('ITEM_ANIMATION_FINISHED', () => {
  // Re-enable UI, advance navigation
});

Animation Manager API:

import { getAnimationManager } from 'kartograf';

const manager = getAnimationManager();
manager.getActiveAnimations();   // string[] of active IDs
manager.cancelAllAnimations();   // stop everything
manager.getStats();              // debug info
11

Error Handling

Common errors and their causes

ErrorCauseSolution
Kartograf: mapInstance is requiredNo mapInstance passed to constructorPass a valid MapLibre GL map instance
mapInstance is requiredNo map instance passed to constructorPass a valid MapLibre GL map instance
Failed to render geometryInvalid feature in a story sceneCheck feature geometry and properties

Graceful degradation

12

Performance

Best practice: Always call kartograf.destroy() when removing a Kartograf instance (e.g., in framework beforeUnmount / useEffect cleanup). This prevents event listener leaks and orphaned animation frames.