michi-vz chart by chart: the maps
August 26, 20264 min read
This is part 8 of 9 in a series touring all 22 michi-vz chart types, family by family. The series starts in Introducing @michi-vz. Part 7 covered tornado and bar-bell.
Eighth stop: geography. Both maps share one principle, that the library bundles no topology, so the shapes on screen are always yours. Every michi-vz chart takes the same props in React, Vue, Svelte, Angular and plain HTML; the first chart below shows all four flavours, the rest show React to keep things short.
The choropleth map
Shade a world or region map by value. One design decision matters here: michi-vz bundles no topology data, so the geography is always a prop. You bring your own GeoJSON, which means your organization's cartographic choices stay yours. This demo fetches a simplified public-domain world file hosted on this site and joins the data by ISO-A3 code:
The data joins against the GeoJSON by feature id (ISO-A3 codes here); colorScale builds a d3 threshold scale from a domain and a colour range:
import world from "./world.json"; // your own GeoJSON FeatureCollection
const data = [
{ id: "BRA", label: "Brazil", value: 3400 },
{ id: "VNM", label: "Vietnam", value: 1900 },
// ...joined to features via joinBy (default: "id")...
];
const colorScale = {
domain: [200, 500, 1000, 2000],
range: ["#e0f2fe", "#7dd3fc", "#38bdf8", "#0284c7", "#075985"],
};
import { ChoroplethMapChart } from "@michi-vz/react";
<ChoroplethMapChart
geography={world}
dataSet={data}
colorScale={colorScale}
width={640}
height={380}
/>;projectionpicks one of 13 d3-geo projections; the default is geoRobinson.joinBy: "name"matches by display name when your data has no stable codes; ids are safer.noDataColorfills countries with no matching row, and a per-rowcolorsupports categorical maps with no scale at all.
Full props on the choropleth map API page.
The symbol map
Choropleths distort the story when the interesting places are small: a city-state vanishes while an empty landmass shouts. The symbol map plots sized circles at real coordinates instead, and a one-shot force simulation pulls overlapping circles apart just enough to keep every one legible:
Each symbol supplies its own coordinates; the library bundles no coordinate table. The muted backdrop landmass is optional:
import world from "./world.json"; // optional muted backdrop
const data = [
{ id: "GVA", label: "Geneva", lng: 6.14, lat: 46.2, value: 95 },
{ id: "HAN", label: "Hanoi", lng: 105.85, lat: 21.03, value: 80 },
// ...lng/lat per item, value drives the radius scale...
];
import { SymbolMapChart } from "@michi-vz/react";
<SymbolMapChart
dataSet={data}
geography={world}
radiusRange={[4, 28]}
width={640}
height={380}
/>;
positionMode: "precise"keeps every circle at its exact projected location, overlaps and all, when accuracy beats legibility.- Omit
geographyentirely for the dot-only look; the backdrop is opt-in. radiusVisibleMinhides items below a raw-value threshold before the layout runs.
Full props on the symbol map API page.
Next in the series: sankey and the fountain.