Aller au contenu principal

WorldMap

Every example on this page is live, drawn by the library's Storybook, where you can also change its props and see the result.

A monochromatic SVG map of the world, shading its countries using fill patterns and optional numeric labels. Supports three map projections: Natural Earth (default), Mercator, and Equirectangular. The map keeps its proportions, filling as much of its box as it can and centered in the rest, in any box it is laid out in. height="fill" sizes the box to the map instead.

Import​

import {
WorldMap,
COUNTRY_NAMES,
countryNameFor,
worldMapAspect,
} from "~lib/data-display/maps/world-map";

Props​

NameTypeRequiredDefaultDescription
dataPartial<Record<CountryName, WorldMapEntry>>YesN/APer-country shading and optional value
projection"natural-earth" | "mercator" | "equirectangular"No"natural-earth"Map projection to use
showValuesbooleanNofalseRender numeric labels at country centroids
markersMapMarker[]NoN/APlaces to mark, each in its shape with an optional name beside it
legendMapLegendEntry[]NoN/AWhat each marker shape stands for, in a row under the map
widthnumber | stringNo300Component width (px or CSS string); with height="fill", the column's width unless given
heightnumber | "fill" | stringNo300Component height (px or CSS string), or "fill" to be as tall as its width makes it

CountryName​

Every country the map draws. Examples: "United States", "China", "India", "Brazil", "Russia", "Japan", "Germany", "United Kingdom", "Australia", "South Africa". COUNTRY_NAMES lists them all.

countryNameFor​

countryNameFor(name: string): CountryName | undefined

The map's name for a country however it is written: a long or official form ("United States of America", "Korea, Republic of"), an ISO 3166-1 two- or three-letter code ("GB", "DEU"), the name it went by ("Burma", "Swaziland") or a common spelling ("Holland", "UK"), in any case, with or without accents. It returns nothing for a country the map does not draw, such as a city state too small for it, so a widget can tell which of its places it can shade and which it should mark with markers instead. Pass the names an installer picks or an API returns through it before keying data with them.

worldMapAspect​

worldMapAspect(projection?: Projection): number

The width over the height of the countries in a projection (Natural Earth unless given), for a widget that sizes the map's box itself. height="fill" uses it for you.

WorldMapEntry​

type WorldMapEntry = {
shading: "solid" | "diagonal" | "dots" | "crosshatch";
value?: number;
};

Projection​

ValueDescription
"natural-earth"Pseudocylindrical compromise projection (default) - good general-purpose
"mercator"Conformal cylindrical - preserves angles but distorts area at high lats
"equirectangular"Simple lat/lon grid - minimal distortion near equator

MapMarker​

type MapMarker = {
latitude: number;
longitude: number;
label?: string;
shape?: "circle" | "square" | "triangle" | "diamond"; // "circle" by default
};

MapLegendEntry​

type MapLegendEntry = {
shape: "circle" | "square" | "triangle" | "diamond";
label: string;
};

Examples​

Default (Natural Earth)​

Ouvrir Default dans Storybook

With Values​

Ouvrir With Values dans Storybook

Mercator​

Ouvrir Mercator dans Storybook

Equirectangular​

Ouvrir Equirectangular dans Storybook

All Patterns​

Ouvrir All Patterns dans Storybook

Many Countries​

Ouvrir Many Countries dans Storybook

With Markers​

markers puts a dot on each place you give, so a place too small to shade, such as Monaco or Singapore, still shows. A label sits beside its dot where there is room for it, and is left out where it would run off the map or cover another marker.

Ouvrir With Markers dans Storybook

On a map drawn small the labels are left out and only the dots show.

Ouvrir Small With Markers dans Storybook
import { WorldMap } from "~lib/data-display/maps/world-map";

const Circuit = ({
name,
latitude,
longitude,
}: {
name: string;
latitude: number;
longitude: number;
}) => (
<WorldMap
data={{}}
markers={[{ latitude, longitude, label: name }]}
width="100%"
height="100%"
/>
);

Marker Shapes​

A marker's shape tells kinds of place apart on one map, such as several species, teams or fleets. Every shape covers the same area, so none reads heavier than another. legend names what each shape stands for in a row under the map, in the order given, wrapping onto further rows when it outgrows the width. The legend is left out of a box too narrow or too short to hold it beside the map, where the map alone says more.

Ouvrir Marker Shapes dans Storybook
<WorldMap
data={{}}
markers={sightings.map(({ latitude, longitude, species }) => ({
latitude,
longitude,
shape: SHAPES[species],
}))}
legend={species.map((name) => ({ shape: SHAPES[name], label: name }))}
width="100%"
height="100%"
/>

Filling a Column's Width​

height="fill" makes the box as tall as its width makes it at the countries' proportion, with the projection fitted to the countries alone, so a map across the top of a column takes no more height than it draws in and the text under it starts where the countries end. In a flex column it spans the column, or width when given, and is the first to shrink when the column runs short, the map then centered in the room that is left. A legend sits under the map, outside its proportion.

Ouvrir Fills Its Width dans Storybook
Ouvrir Fills A Short Column dans Storybook
<div className="flex h-full flex-col gap-2">
<WorldMap data={data} height="fill" />
<Heading level={4}>Sightings</Heading>
</div>

Countries By Any Name​

Ouvrir Countries By Any Name dans Storybook
import { WorldMap, countryNameFor } from "~lib/data-display/maps/world-map";

const data = Object.fromEntries(
apiCountries.flatMap((written) => {
const country = countryNameFor(written);
return country ? [[country, { shading: "solid" }]] : [];
}),
);

See Also​

  • USMap - United States detail map
  • UKMap - United Kingdom detail map
  • EuropeMap - Europe detail map
  • Badge - Inline label for status or counts