ApexMaps 0.3.0 is about texture, and a handful of interactions the 0.2.0 maps were missing. A flat fill is one color per feature; fill.pattern lays one of eight tiles over the color a scale already chose, and fill.image clips a picture to each region's own outline. Alongside it: flow: true sends beads travelling along a route so a connection says which way something moves, an orthographic globe now spins under the pointer instead of sliding around inside its box, a drilldown divides the parent shape into its children, and on-screen + / - controls give zoom its first keyboard and mouse path.

There is one breaking change, and it is why this is a minor rather than a patch: the canvas renderer is gone. Nothing else about a 0.2.0 configuration changes.

Key takeaways

ChangeWhat it is
Pattern fills (fill.pattern)Eight textures over the scale's color, for print, color-vision safety, and qualitative maps. Premium.
Image fills (fill.image)A picture clipped to each region's outline, a flag or a tile per feature. Premium.
Flow (flow: true)Beads travelling from to to along an arc or line. No new gate.
Globe rotationA versor drag spins an orthographic globe; flyTo reaches the far side. Free.
Zoom controlsOn-screen + / - / reset and a keyboard path, on by default. Free.
Drilldown transitionThe parent shape divides into its children rather than cutting.
Legend upgradesA side column, a gradient bar for classed scales, and a hover marker.
Breaking: canvas removedchart.renderer / chart.rendererThreshold are gone; SVG is the only renderer.

Texture: pattern and image fills

There are three places a single color per feature is not enough. Print and photocopy collapse a five-step ramp to about three. Two classes of a diverging ramp can read as one to a reader with a color-vision deficiency. And when the classes are kinds rather than amounts, a sequential ramp asserts an order that is not in the data. fill.pattern adds a second channel over the color the scale resolved, rather than replacing it.

series: [
  {
    type: 'choropleth',
    data,
    scale: { type: 'quantile', classes: 5 },
    fill: { pattern: { type: 'dots', size: 10 } },
  },
]

Eight tiles are built in (dots, squares, checks, lines, grid, diagonal, crosshatch, and custom), and the tile can be decided per feature with a callback that is handed the color the scale chose. The defaults are the design: the ink picks a legible color for its background, the tile background defaults to the class color so texture adds to the encoding rather than replacing it, and the pattern holds its size on screen as the reader zooms instead of growing with the geography.

fill.image clips a picture to each region's own outline, one image per feature:

fill: {
  image: {
    src: ({ key }) => `/flags/${key.toLowerCase()}.svg`,
    fit: 'cover',
  },
}

Both are Premium features, priced separately because they are separable purchases: texture is a legibility and print concern, imagery is a different product. The accessibility layer, okabeIto, and the automatic diverging-palette selection stay free permanently, as the free tier's answer to the same color-vision problem. See Pattern & Image Fills, the pattern demo, and the image-fill demo.

Flow: which way the traffic moves

An arc says two places are related. It does not say which way anything moves, and on a hub map every route leaves the same airport, so the reader cannot infer it either. flow: true sends beads along each route from from toward to:

{
  type: 'arc',
  data: ROUTES,
  geodesic: true,
  flow: true, // beads, from -> to
}

It costs nothing per frame: the mechanism is one dashed companion path per route, animated on its dash offset, so the phase is a pure function of time and panning cannot disturb it. The beads are anchored to the ground and each camera-following property is bounded, so a route that opened as five beads does not become a dotted line at full zoom. Flow rides on the already-licensed arc and line series and adds no new gate. See Arcs and Routes.

A globe you can spin

A drag on an orthographic projection used to pan it, sliding a picture of the earth around inside its box and leaving the far hemisphere permanently unreachable. Now it spins the sphere.

new ApexMaps(el, {
  geo: { projection: 'orthographic' },
  interaction: { rotate: { enabled: 'auto', inertia: true } },
})

map.rotateTo([-77, 39])              // absolute [lambda, phi], as a drag would
map.camera.flyTo({ center: [2.35, 48.85] }) // now turns the globe to Paris

Dragging is versor-based, so the point under the cursor stays under it at any latitude however far the globe has already turned. Camera moves know it too: where re-centering means turning, a center target becomes a rotation interpolated as a quaternion slerp (the short way round, no swing-out over a pole), and a flyTo scales its duration by the angle covered so a turn and a zoom land together. Everything laid out flat, conics included, is pixel-identical. See Zoom, Pan & Camera.

Zoom controls and a keyboard path

Wheel, pinch and double-click are all gestures, and a map whose only way to change scale is a gesture has no keyboard path and loses anyone on a trackpad over a scrolling page. So +, - and a reset now render by default wherever zoom is enabled:

interaction: {
  zoom: {
    step: 1.6,
    controls: { show: true, position: 'top-right', reset: true },
  },
}

They are real, focusable buttons that go flat at each end of the range, + = - _ 0 do the same from the keyboard, and the group sits in HTML over the plot so it never lands in the exported SVG. interaction.zoom.controls: false removes them for a dashboard that wants a clean tile.

A drilldown that divides the parent

Clicking a state used to frame it and then swap in its counties in one synchronous draw, which read as a cut. animate: 'zoom' (still the default) is now three parts in the order the reader sees them: the child level is handed the exact screen box the parent occupied and eases to its own fit, the outgoing level fades out above it, and the incoming marks start as a flat copy of the parent's fill and divide into their children from the middle outward. It rides the transitions the map already declares, so there is no per-frame cost, and it honors prefers-reduced-motion without knowing it exists. See Drilldown.

Legends: a side column and a hover marker

legend.position: 'left' | 'right' turns the legend into a column with a vertical gradient bar. Hovering a feature now runs an arrow along the bar to where that feature falls on the scale, so the reader gets the value-to-color mapping read forwards instead of matching colors by eye, and 'gradient' is finally available for classed scales as a bar of hard bands. See Legends, Labels & Tooltips.

Breaking: the canvas renderer is gone

chart.renderer, chart.rendererThreshold, and the canvas tier behind them are removed. SVG is the only geometry renderer again. Options are not whitelisted, so a config still passing chart.renderer is ignored rather than rejected: nothing throws, and the map renders in SVG. The performance model is unchanged and still free in every tier: a camera frame writes exactly one transform regardless of feature count. Nothing else about a 0.2.0 configuration changes.

See it live

This choropleth is the real library rendering in your browser. The new 0.3.0 features each have their own runnable page in the demos gallery.

Go deeper

Summary

ApexMaps 0.3.0 gives the map a second channel with pattern and image fills, direction with flow, and a globe that finally turns, while removing the canvas tier that a map with a few thousand features never needed. Community series stay free; patterns, imagery, routes, drilldown, annotations, clustering, custom projections, linked maps, and story mode are Premium, and evaluate with a watermark. Read the full docs or browse the demos.

Frequently asked questions

What is new in ApexMaps 0.3.0?

Pattern fills and image fills (fill.pattern and fill.image), directional flow beads on arc and line routes, a draggable orthographic globe with rotation-aware camera moves, on-screen zoom controls with a keyboard path, a drilldown transition that divides the parent shape into its children, and legend upgrades (a side column, a real gradient bar for classed scales, and a hover marker). The canvas renderer is removed.

Are pattern and image fills free?

No. Patterns (fill.pattern) and imagery (fill.image) are two separate Premium features. Both work without a key for evaluation, with a watermark on the map; a valid key removes it. Flow adds no new gate because arc and line series are already licensed.

Is the canvas renderer still available in ApexMaps?

No. The canvas tier is removed in 0.3.0 and SVG is the only renderer. A config still passing chart.renderer or chart.rendererThreshold is ignored rather than rejected, so nothing throws; the map renders in SVG.

How do I make an ApexMaps globe spin?

Use the orthographic projection. Rotation is on by default there (interaction.rotate defaults to 'auto'), so a drag spins the sphere. Move it programmatically with map.rotateTo([lambda, phi]) or fly to a location with map.camera.flyTo({ center: [lon, lat] }), which now turns the globe instead of panning.