Map with Dynamic Pie Charts
Pie charts on a map: each of four regions gets its own pie of made-up sales by product line, sized by the region’s total sales.
About this map
When to put charts on a map
A small chart at each place shows a breakdown and its location at once: what sells in each region, and where. Each pie here is a full chart of its own, placed as a bullet of a map point series, with its area matched to the region’s total. Keep to a few places and a few slices, or the pies get too small to read.
Good for
- Breakdowns by region, like sales by product
- Election results by area
- A few places with a few parts each
Think twice when
- Many places: color the regions by one value
- Close comparisons: bars beside the map
- More than four or five slices: they get too thin
For developers
Get the code.
Built with amCharts 5, a JavaScript library. The code includes your theme and renderer (canvas or SVG), but not the changes you make with the controls.
For projects that use npm:
How it reads:
Using Claude? Install the amCharts plugin first, so it works from our docs and examples.
npm install @amcharts/amcharts5 and @amcharts/amcharts5-geodata. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code.How it reads:
"type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.Using Claude? Install the amCharts plugin first, so it works from our docs and examples.
// Create root element
// https://docs.amcharts.com/v5/getting-started/#root-element
var root = am5.Root.new("chartdiv");
// Set themes
// https://docs.amcharts.com/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// ====================================
// Create map
// ====================================
// Create the map chart
// https://docs.amcharts.com/v5/charts/map-chart/
var map = root.container.children.push(
am5map.MapChart.new(root, {
minZoomLevel: 0.5, // can zoom out to half the fitted size
// go to the home view once the map is fitted
autoHome: true,
panX: "none", // no dragging sideways (up and down still pans)
projection: am5map.geoNaturalEarth1() // a compromise world projection with rounded sides
})
);
// Add zoom control
// https://docs.amcharts.com/v5/charts/map-chart/map-pan-zoom/#zoom-control
var zoomControl = map.set("zoomControl", am5map.ZoomControl.new(root, {})); // + and - zoom buttons
// the home button is hidden by default
zoomControl.homeButton.set("visible", true);
// Create polygon series for the continents
// https://docs.amcharts.com/v5/charts/map-chart/map-polygon-series/
var polygonSeries = map.series.push(
am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_continentsLow // continents, not countries, in low detail
})
);
// gray land in light and dark themes: the theme's text color, mostly see-through
polygonSeries.mapPolygons.template.setAll({
fill: root.interfaceColors.get("alternativeBackground"),
fillOpacity: 0.15
});
// Add legend: a key to the product lines, which every pie shows in the same colors
// https://docs.amcharts.com/v5/concepts/legend/
var legend = map.children.push(am5.Legend.new(root, {
centerX: am5.p50, // the legend's middle...
x: am5.p50, // ...at the middle of the map
centerY: am5.p100, // its bottom edge...
y: am5.p100, // ...at the map's bottom
clickTarget: "none", // a key only: a click would hide the slice in one pie alone
background: am5.RoundedRectangle.new(root, {
fill: root.interfaceColors.get("background"), // a box in the background color...
fillOpacity: 0.7 // ...slightly see-through
})
}));
legend.valueLabels.template.set("forceHidden", true); // no value labels in the legend
// Create point series for the pie charts
// https://docs.amcharts.com/v5/charts/map-chart/map-point-series/
var pointSeries = map.series.push(
am5map.MapPointSeries.new(root, {})
);
// All pie charts share one template, and all region names another, so each can be changed at once
var pieTemplate = am5.Template.new({
// the pie fills its chart's full size instead of the default 80%
radius: am5.p100,
centerX: am5.p50, // centered on its map point...
centerY: am5.p50 // ...both ways
});
var titleTemplate = am5.Template.new({
centerX: am5.p50, // the name centered over the point...
centerY: am5.p100 // ...and anchored by its bottom edge
});
// A pie chart as a bullet: each one is a chart of its own. It goes into the root container first, so it picks up
// the themes and colors, and the bullet then moves it onto the map.
// https://docs.amcharts.com/v5/charts/percent-charts/pie-chart/
pointSeries.bullets.push(function(root, series, dataItem) {
var region = dataItem.dataContext;
var chart = root.container.children.push(am5percent.PieChart.new(root, {
width: region.size, // sized by the region's total, worked out below
height: region.size
}, pieTemplate));
var pieSeries = chart.series.push(am5percent.PieSeries.new(root, {
valueField: "value",
categoryField: "category"
}));
// every third palette color, so neighboring slices are easy to tell apart
pieSeries.get("colors").set("step", 3);
pieSeries.labels.template.set("forceHidden", true); // no slice labels...
pieSeries.ticks.template.set("forceHidden", true); // ...and no ticks: the pies are too small for them
pieSeries.data.setAll(region.pieData);
// the first pie's slices fill the legend
if (!legend.data.length) {
legend.data.setAll(pieSeries.dataItems);
}
return am5.Bullet.new(root, {
sprite: chart
});
});
// The region's name above its pie
pointSeries.bullets.push(function(root, series, dataItem) {
var region = dataItem.dataContext;
return am5.Bullet.new(root, {
sprite: am5.Label.new(root, {
text: region.title, // the region's name
dy: region.size * -0.5 // lifted by half the pie's size, to sit above it
}, titleTemplate)
});
});
// ====================================
// Data
// ====================================
// Made-up sales of four product lines in four regions
var regions = [{
title: "North America",
latitude: 39.563353,
longitude: -99.316406,
pieData: [
{ category: "Phones", value: 1200 },
{ category: "Laptops", value: 765 },
{ category: "Tablets", value: 500 },
{ category: "Accessories", value: 260 }
]
}, {
title: "Europe",
latitude: 50.896104,
longitude: 19.160156,
pieData: [
{ category: "Phones", value: 600 },
{ category: "Laptops", value: 450 },
{ category: "Tablets", value: 200 },
{ category: "Accessories", value: 150 }
]
}, {
title: "Asia",
latitude: 47.212106,
longitude: 103.183594,
pieData: [
{ category: "Phones", value: 1050 },
{ category: "Laptops", value: 512 },
{ category: "Tablets", value: 266 },
{ category: "Accessories", value: 199 }
]
}, {
title: "Africa",
latitude: 11.081385,
longitude: 21.621094,
pieData: [
{ category: "Phones", value: 420 },
{ category: "Laptops", value: 130 },
{ category: "Tablets", value: 60 },
{ category: "Accessories", value: 90 }
]
}];
// Size each pie by its region's total, so that its area matches the total: the largest is 110 pixels across
var totals = regions.map(function(region) {
return region.pieData.reduce(function(sum, slice) { return sum + slice.value; }, 0);
});
var largest = Math.max.apply(null, totals); // the biggest total
// one map point per region, with its position, name, pie size and slices
for (var i = 0; i < regions.length; i++) {
var region = regions[i];
pointSeries.data.push({
geometry: { type: "Point", coordinates: [region.longitude, region.latitude] }, // longitude first
title: region.title,
size: Math.round(110 * Math.sqrt(totals[i] / largest)), // square root: the area grows with the total
pieData: region.pieData
});
}
More map tools.

SVG Map Generator
Any region, any projection
Pick a map and projection, simplify it and paint regions, then export SVG or PNG.
Pixel Map Generator
Dotted and pixel-art maps
Turn any map into dots, squares, hexagons or diamonds for posters and slides.

SVG Maps
427 maps, free to download
World, continents, countries and regions, with every region as its own named path.



