Skip to content

Geo mark ^0.6.1

The geo mark draws geographic features — polygons, lines, points, and other geometry — often as thematic maps. It works with Plot’s projection system. For example, the choropleth map below shows unemployment by county in the United States.

Fork
js
Plot.plot({
  projection: "albers-usa",
  color: {
    type: "quantile",
    n: 9,
    scheme: "blues",
    label: "Unemployment (%)",
    legend: true
  },
  marks: [
    Plot.geo(counties, {
      fill: (d) => d.properties.unemployment,
      title: (d) => `${d.properties.name}\n${d.properties.unemployment}%`
    })
  ]
})

A geo mark’s data is typically GeoJSON. You can pass a single GeoJSON object, a feature or geometry collection, or an array or iterable of GeoJSON objects.

The size of Point and MultiPoint geometries is controlled by the r option. For example, below we show earthquakes in the last seven days with a magnitude of 2.5 or higher as reported by the USGS. As with the dot mark, the effective radius is controlled by the r scale, which is by default a sqrt scale such that the area of a point is proportional to its value. And likewise point geometries are by default sorted by descending radius to reduce occlusion, drawing the smallest circles on top. Set the sort option to null to use input order instead.

Fork
js
Plot.plot({
  projection: "equirectangular",
  r: {transform: (r) => Math.pow(10, r)}, // Richter to amplitude
  marks: [
    Plot.geo(land, {fill: "currentColor", fillOpacity: 0.2}),
    Plot.sphere(),
    Plot.geo(earthquakes, {
      r: (d) => d.properties.mag,
      fill: "red",
      fillOpacity: 0.2,
      stroke: "red",
      title: (d) => d.properties.title,
      href: (d) => d.properties.url,
      target: "_blank"
    })
  ]
})

TIP

Click on any of the earthquakes above to see details.

The graticule helper draws a uniform grid of meridians (lines of constant longitude) and parallels (lines of constant latitude) every 10° between ±80° latitude; for the polar regions, meridians are drawn every 90°. The sphere helper draws the outline of the projected sphere.

Fork
js
Plot.plot({
  inset: 2,
  projection: {type: "orthographic", rotate: [0, -30, 20]},
  marks: [
    Plot.sphere({fill: "white", stroke: "currentColor"}),
    Plot.graticule({strokeOpacity: 0.3})
  ]
})

The geo mark’s geometry channel can be used to generate geometry from a non-GeoJSON data source. For example, below we visualize the shockwave created by the explosion of the Hunga Tonga–Hunga Haʻapai volcano on January 15, 2022 with a series of geodesic circles of increasing radius.

Fork
js
Plot.plot({
  projection: {
    type: "equal-earth",
    rotate: [90, 0]
  },
  color: {
    legend: true,
    label: "Distance from Tonga (km)",
    transform: (d) => 111.2 * d, // degrees to km
    zero: true
  },
  marks: [
    Plot.geo(land),
    Plot.geo([0.5, 179.5].concat(d3.range(10, 171, 10)), {
      geometry: d3.geoCircle().center([-175.38, -20.57]).radius((r) => r),
      stroke: (r) => r,
      strokeWidth: 2
    }),
    Plot.sphere()
  ]
})

The geo mark doesn’t have x and y channels; to derive those, for example to add interactive tips, you can apply a centroid transform on the geometries.

Fork
js
Plot.plot({
  projection: "albers-usa",
  marks: [
    Plot.geo(statemesh, {strokeOpacity: 0.2}),
    Plot.geo(nation),
    Plot.dot(states, Plot.centroid({fill: "red", stroke: "white"})),
    Plot.tip(states, Plot.pointer(Plot.centroid({title: (d) => d.properties.name})))
  ]
})

The geo mark supports faceting. Below, a comic strip of sorts shows the locations of Walmart store openings in past decades.

Fork
js
Plot.plot({
  margin: 0,
  padding: 0,
  projection: "albers",
  fy: {interval: "10 years"},
  marks: [
    Plot.geo(statemesh, {strokeOpacity: 0.2}),
    Plot.geo(nation),
    Plot.geo(walmarts, {fy: (d) => d.properties.date, r: 1.5, fill: "blue"}),
    Plot.axisFy({frameAnchor: "top", dy: 30, tickFormat: (d) => `${d.getUTCFullYear()}’s`})
  ]
})

INFO

This uses the interval scale option to bin temporal data into facets by decade.

Lastly, the geo mark is not limited to spherical geometries! Plot’s projection system includes planar projections, which allow you to work with shapes — such as contours — generated on an arbitrary flat surface.

Geo options

The geometry channel specifies the geometry (GeoJSON object) to draw; if not specified, the mark’s data is assumed to be GeoJSON.

In addition to the standard mark options, the r option controls the size of Point and MultiPoint geometries. It can be specified as either a channel or constant. When r is specified as a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel and the effective radius is controlled by the r scale. If the r option is not specified it defaults to 3 pixels. Geometries with a nonpositive radius are not drawn. If r is a channel, geometries will be sorted by descending radius by default.

geo(data, options)

js
Plot.geo(counties, {fill: (d) => d.properties.rate})

Returns a new geo mark with the given data and options. If data is a GeoJSON feature collection, then the mark’s data is data.features; if data is a GeoJSON geometry collection, then the mark’s data is data.geometries; if data is some other GeoJSON object, then the mark’s data is the single-element array [data]. If the geometry option is not specified, data is assumed to be a GeoJSON object or an iterable of GeoJSON objects.

sphere(options) ^0.6.1

js
Plot.sphere()

Returns a new geo mark with a Sphere geometry object and the given options.

graticule(options) ^0.6.1

js
Plot.graticule()

Returns a new geo mark with a 10° global graticule geometry object and the given options.