Skip to main content

MapChart

The MapChart component renders a Highcharts map series, useful for visualizing data across geographical regions — for example a portfolio's exposure by continent or country.

Map data is not bundled with Kyber. You supply the topology (GeoJSON or TopoJSON) for the map you need via the mapData prop. The examples below fetch a topology from the Highcharts CDN, but you can load it however you like.

Exposure by continent

By default each region is colored categorically from the Kyber chart palette (colorByPoint). Data points are joined to the topology by the joinBy key (hc-key by default).

Result
Loading...
Live Editor
function GeographicalDiversification() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-continents.geo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="geographical-diversification"
			title="Geographical Diversification"
			formatType="percent"
			mapData={mapData}
			options={{
				mapView: {
					projection: {
						name: 'None',
					},
				},
			}}
			data={[
				{ 'hc-key': 'na', 'name': 'North America', 'value': 44.3 },
				{ 'hc-key': 'eu', 'name': 'Europe', 'value': 30.5 },
				{ 'hc-key': 'as', 'name': 'Asia', 'value': 19.0 },
				{ 'hc-key': 'sa', 'name': 'South America', 'value': 6.2 },
				{ 'hc-key': 'af', 'name': 'Africa', 'value': 2.7 },
				{ 'hc-key': 'oc', 'name': 'Oceania', 'value': 1.0 },
			]}
		/>
	);
}

render(<GeographicalDiversification />);

Exposure by country

Any Highcharts topology works. Here we use the detailed world map. By default (fitToData) the view zooms to fit the regions that have data, so the user lands on the meaningful part of the map instead of the whole world; regions without data stay visible but out of focus. Users can zoom and pan further with the map navigation controls (enableZoom). Set fitToData={false} to always start from the full map extent.

Result
Loading...
Live Editor
function CountryExposure() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-highres.geo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="country-exposure"
			title="Exposure by Country"
			formatType="percent"
			joinBy="hc-key"
			mapData={mapData}
			data={[
				{ 'hc-key': 'us', 'name': 'United States', 'value': 44.3 },
				{ 'hc-key': 'gb', 'name': 'United Kingdom', 'value': 12.5 },
				{ 'hc-key': 'de', 'name': 'Germany', 'value': 10.0 },
				{ 'hc-key': 'jp', 'name': 'Japan', 'value': 9.5 },
				{ 'hc-key': 'cn', 'name': 'China', 'value': 8.0 },
				{ 'hc-key': 'ca', 'name': 'Canada', 'value': 5.5 },
				{ 'hc-key': 'br', 'name': 'Brazil', 'value': 4.2 },
				{ 'hc-key': 'au', 'name': 'Australia', 'value': 3.0 },
				{ 'hc-key': 'in', 'name': 'India', 'value': 3.0 },
			]}
		/>
	);
}

render(<CountryExposure />);

Autofit Data to Region

By default the zoom area will fit to geographical region of provided data.

Result
Loading...
Live Editor
function CountryExposure() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-highres.geo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="country-exposure"
			title="Autofit Data"
			formatType="percent"
			joinBy="hc-key"
			mapData={mapData}
			data={[
				{ 'hc-key': 'us', 'name': 'United States', 'value': 44.3 },
				{ 'hc-key': 'ca', 'name': 'Canada', 'value': 5.5 },
			]}
		/>
	);
}

render(<CountryExposure />);

Reset zoom

Set showZoomReset to add a reset button to the zoom controls. After the user has zoomed or panned, the button returns the map to its starting view — re-fitting to the data when fitToData is enabled, or the full map extent otherwise. Requires enableZoom.

Result
Loading...
Live Editor
function ResetZoom() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-highres.geo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="reset-zoom"
			title="Exposure by Country"
			formatType="percent"
			joinBy="hc-key"
			showZoomReset
			mapData={mapData}
			data={[
				{ 'hc-key': 'us', 'name': 'United States', 'value': 44.3 },
				{ 'hc-key': 'gb', 'name': 'United Kingdom', 'value': 12.5 },
				{ 'hc-key': 'de', 'name': 'Germany', 'value': 10.0 },
				{ 'hc-key': 'jp', 'name': 'Japan', 'value': 9.5 },
				{ 'hc-key': 'cn', 'name': 'China', 'value': 8.0 },
			]}
		/>
	);
}

render(<ResetZoom />);

Choropleth (value based) coloring

Set colorByPoint={false} and pass a colorAxis through the options prop to shade regions by value instead of coloring them categorically.

Result
Loading...
Live Editor
function Choropleth() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-continents.geo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="choropleth"
			title="Exposure Intensity"
			formatType="percent"
			colorByPoint={false}
			mapData={mapData}
			options={{
				colorAxis: {
					min: 0,
					minColor: '#E9F0F6',
					maxColor: '#315F87',
				},
			}}
			data={[
				{ 'hc-key': 'na', 'name': 'North America', 'value': 44.3 },
				{ 'hc-key': 'eu', 'name': 'Europe', 'value': 30.5 },
				{ 'hc-key': 'as', 'name': 'Asia', 'value': 19.0 },
				{ 'hc-key': 'sa', 'name': 'South America', 'value': 6.2 },
				{ 'hc-key': 'af', 'name': 'Africa', 'value': 2.7 },
				{ 'hc-key': 'oc', 'name': 'Oceania', 'value': 1.0 },
			]}
		/>
	);
}

render(<Choropleth />);

Projections

Highcharts can reproject the map to any of its built-in projections. Pass a mapView.projection through the options prop — here we use the Miller cylindrical projection. fitToData is disabled so the whole projected world is visible.

Result
Loading...
Live Editor
function MillerProjection() {
	const [mapData, setMapData] = useState(null);

	useEffect(() => {
		fetch('https://code.highcharts.com/mapdata/custom/world-continents.topo.json')
			.then((response) => response.json())
			.then(setMapData);
	}, []);

	if (!mapData) return <Spinner />;

	return (
		<MapChart
			id="miller-projection"
			title="Miller Projection"
			formatType="percent"
			fitToData={false}
			mapData={mapData}
			options={{
				mapView: {
					projection: {
						name: 'Miller',
					},
				},
			}}
			data={[
				{ 'hc-key': 'na', 'name': 'North America', 'value': 44.3 },
				{ 'hc-key': 'eu', 'name': 'Europe', 'value': 30.5 },
				{ 'hc-key': 'as', 'name': 'Asia', 'value': 19.0 },
				{ 'hc-key': 'sa', 'name': 'South America', 'value': 6.2 },
				{ 'hc-key': 'af', 'name': 'Africa', 'value': 2.7 },
				{ 'hc-key': 'oc', 'name': 'Oceania', 'value': 1.0 },
			]}
		/>
	);
}

render(<MillerProjection />);

Update Highcharts modules

Map is not included in the default Highcharts bundle. You will need to extend Highcharts with the Map module.

import Highcharts from 'highcharts';
import Map from 'highcharts/modules/map';

Map(Highcharts);

You also need to supply a topology. You can fetch one from the Highcharts CDN (as shown above) or install @highcharts/map-collection and import the map you need:

import worldMap from '@highcharts/map-collection/custom/world.topo.json';

<MapChart mapData={worldMap} data={data} />;

Props