Pixel Maps

A pixel map is a choropleth with a different mark. The rows, the join and the colour scale are the same; instead of filling each region's outline, the map lays a lattice of dots over the land and paints every dot that falls inside a region with that region's colour. Added in ApexMaps 1.1.

series: [
  {
    type: 'pixel',
    name: 'Index',
    joinBy: 'name',
    data,                     // the same rows a choropleth takes
    shape: 'hexagon',         // circle, square, hexagon or diamond
    spacing: 2.5,             // degrees between dots on the default geo grid
    scale: { palette: 'viridis' },
  },
]

Change the type of a choropleth you already have to 'pixel' and it draws. Everything upstream of the paint is shared: joins and fuzzyJoin, normalizeBy, the scale and its classes, and drilldown. Each region stays one element, so the legend, tooltip, hover, selection and keyboard focus treat it as one region, and the gaps between its dots answer the pointer as the region they sit in. The legend draws each swatch as a few of the series' dots.

The one choropleth option a pixel map does not take is fill: pattern and image fills apply to outlines.

Options

OptionTypeDefaultWhat it controls
shape'circle' | 'square' | 'hexagon' | 'diamond''circle'The mark drawn at each lattice point
grid'geo' | 'screen''geo'What the lattice is fixed to: the ground or the screen
spacingnumberabout 120 dots across (geo), 8 (screen)Distance between dots: degrees on a geo grid, measured at the middle of the map; screen pixels on a screen grid
sizenumber | '<n>%''80%'Dot size, as a share of spacing or in pixels at the opening zoom
lattice'square' | 'staggered'by shapeHow rows sit against each other
equalAreabooleantrueOn a globe, thin rows towards the poles so each dot covers the same ground

The default geo spacing is rounded to a readable step: a world map gets 3°, a single country a fraction of one.

Shapes tile at 100%

Each shape sits on a lattice made for it. Squares line up in a square grid; circles, hexagons and diamonds are staggered, every other row shifted half a step, with the row spacing chosen so the shape packs. At size: '100%' neighbouring marks meet edge to edge: squares make a solid grid, and hexagons and diamonds tile. Larger values are clamped to 100%, because past it dots overlap and which one ends up on top is an accident of drawing order.

Set lattice to override the pairing, for example squares staggered like brickwork.

Fixed to the ground or to the screen

grid: 'geo' lays the lattice evenly over the map as it opens, and from then on every dot is a place. Zooming in magnifies the dots, a resize moves them with the land, and nothing is resampled.

grid: 'screen' keeps the spacing even on screen whatever the projection does to the ground underneath. It is resampled as the reader zooms, at the same quantized levels clustering and hexbins use, so a zoom adds detail instead of magnifying, and a pan never resamples.

{ type: 'pixel', data, joinBy: 'name', grid: 'screen', spacing: 6 }

On a globe

With an orthographic projection the lattice is laid on the sphere itself, in rows along the parallels, so the dots turn with the world when it is dragged. A globe accepts only the geo grid: a screen grid would be resampled on every frame of a spin, so grid: 'screen' is reported and drawn as 'geo'.

equalArea (on by default) thins each row towards the poles, so a row near the pole does not carry as many dots as the equator on a fraction of the length. It applies only on a globe; on a flat map it is reported and ignored, because the lattice is laid on the map as drawn, which on an equal-area projection is equal-area already.

geo: {
  map: 'world/countries@110m',
  projection: { name: 'orthographic', rotate: [-20, -25, 0] },
},
series: [{ type: 'pixel', joinBy: 'name', data, shape: 'hexagon', spacing: 2.5, size: '88%' }]

No region lost for being small

A region the lattice steps over still gets a dot, placed at the nearest free lattice point or borrowed from a neighbour. At the default spacing every one of the 177 countries on the world map is drawn, Luxembourg and Brunei included. Debug mode names any region that still gets no dot.

Licensing

Pixel maps are a licensed feature, sold with the hex tile layouts. Without a key they work in full with a watermark on the map, so you can try them on your own data first. See Licensing.

See the Pixel Map demo for every option on a control panel, a hexagon globe, and a map of Europe at sub-degree spacing.