Annotations

Premium feature

Editorial annotations is a Premium feature

Available on the Premium and OEM plans. Annotations work without a key for evaluation, with a watermark on the map; call ApexMaps.setLicense(key) to remove it.

Data on a map says what is where. An annotation says why you published it, which is usually the actual point. ApexMaps has three anchoring modes because there are three things an author points at: a coordinate, a feature by key, or an area.

Anchor a callout to a coordinate, a feature, or an area

const map = new ApexMaps(document.getElementById('map'), {
  geo: { map: 'world/countries@110m' },
  annotations: {
    points: [
      {
        at: [-77.04, -12.05],
        label: { text: 'Humboldt current\nupwelling', position: 'left' },
        marker: { shape: 'pin', size: 12 },
        connector: true,
      },
    ],
    features: [
      {
        key: 'IND',
        label: { text: 'Fastest-growing\nof the ten largest', position: 'bottom' },
        outline: true,
      },
    ],
    areas: [
      {
        bounds: [-20, 10, 40, 30], // [west, south, east, north]
        label: 'The Sahel',
        fill: '#FEB019',
        fillOpacity: 0.16,
      },
    ],
  },
  series: [{ type: 'choropleth', name: 'Illustrative index', data: [] }],
})

await map.render()
KindAnchored toUse it for
pointsA [lon, lat] coordinate (at)"Epicentre", "the new plant", a place with no feature of its own
featuresA feature key, at the same point the label engine usesCalling out a country, state, or county so the chip tracks it through a projection change
areasA bounds box or a GeoJSON geometry"The drought region", any region that is not one feature

A feature annotation can also trace the shape's own outline with outline: true, or a custom stroke: outline: { color: '#00E396', width: 2, dashArray: '5 3' }.

Annotations win, labels yield

Turn on dataLabels alongside annotations and watch which one gives way. Generated feature labels that would collide with an annotation are dropped, never the other way round: you placed the annotation deliberately, and the label came from a layout rule, so the rule yields. Most charting libraries resolve this backwards and silently lose whichever one arrived second.

await map.updateOptions({ dataLabels: { enabled: true } })

map.labels.placedCount  // labels that survived collision
map.labels.droppedCount // labels dropped because an annotation already occupied the space
map.annotations.count   // annotations actually resolved and drawn

Label, marker, and connector options

The label shorthand accepts a plain string (label: 'Amazon basin'), which is equivalent to label: { text: 'Amazon basin' }.

label optionDescription
textThe chip text. \n breaks it onto multiple lines.
position'top' (default), 'bottom', 'left', 'right', or 'center' relative to the anchor.
offsetX, offsetYNudge the chip after position is applied.
backgroundChip fill colour. 'none' draws bare, haloed text with no chip.
color, fontSize, fontWeightText styling.
borderColor, borderWidth, borderRadius, paddingChip styling.
marker optionDescription
showSet false to anchor a label with no visible marker.
shapeAny of the seven marker shapes: circle, square, diamond, triangle, star, cross, pin.
size, fill, strokeMarker styling.

connector draws a leader line from the anchor to an offset label: connector: true for the default dashed line, or an object with color, width, and dashArray.

Behavior worth knowing

  • Anchors live in world space, text in screen space. The anchor tracks the geography through pan and zoom, while the chip keeps its own size, because editorial type that grows with the camera stops being type and becomes decoration.
  • Annotations are inert to the pointer. A chip never swallows the hover or click of the country underneath it, so the map's own tooltips keep working exactly as if the annotation were not there.
  • Areas go through the projection. A bounds box over the Arctic bows the way the graticule does rather than staying a flat screen-space rectangle.
  • A key that matches nothing is reported, not silently dropped. If features[].key does not exist on the current map, the dev-mode diagnostics say so by name instead of leaving you to notice a missing chip.

Clear or toggle annotations

Pass an empty set to updateOptions to turn annotations off without touching anything else:

await map.updateOptions({ annotations: { points: [], features: [], areas: [] } })

Removing the evaluation watermark

Annotations render in full without a key, with a watermark on the map. Call ApexMaps.setLicense(key) once, before rendering, to remove it from every map on the page:

ApexMaps.setLicense('APEX-xxxxxxxx')

For drilling into a feature's own children, see Drilldown. For linking a selection across two maps, see Selection.