Grouped Countries Map
A map of the 27 countries of the European Union, grouped by when they joined. Hover a country and its whole group lights up; the legend switches groups off and on.
About this map
When to group areas
Coloring areas by a few categories answers which ones belong together: members and non-members, sales regions, voting blocs. Lighting up the whole group on hover makes the grouping hard to miss. It works best with a handful of groups; past six or seven, the colors are hard to tell apart.
Good for
- Alliances, unions and trade blocs
- Sales or service regions
- Countries by category or status
Think twice when
- Values on a scale: a heat map shows the order
- Many groups: the colors blur together
- Changes over time: a map with a timeline
For developers
Get the code.
Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.
For projects that use npm:
How it reads:
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.
// Data: the 27 members of the European Union, grouped by when they joined
var groupData = [
{
"name": "Joined before 2004",
"data": [
{ "id": "AT", "joined": "1995"},
{ "id": "IE", "joined": "1973"},
{ "id": "DK", "joined": "1973"},
{ "id": "FI", "joined": "1995"},
{ "id": "SE", "joined": "1995"},
{ "id": "IT", "joined": "1957"},
{ "id": "FR", "joined": "1957"},
{ "id": "ES", "joined": "1986"},
{ "id": "GR", "joined": "1981"},
{ "id": "DE", "joined": "1957"},
{ "id": "BE", "joined": "1957"},
{ "id": "LU", "joined": "1957"},
{ "id": "NL", "joined": "1957"},
{ "id": "PT", "joined": "1986"}
]
}, {
"name": "Joined in 2004",
"data": [
{ "id": "LT", "joined": "2004" },
{ "id": "LV", "joined": "2004" },
{ "id": "CZ", "joined": "2004" },
{ "id": "SK", "joined": "2004" },
{ "id": "SI", "joined": "2004" },
{ "id": "EE", "joined": "2004" },
{ "id": "HU", "joined": "2004" },
{ "id": "CY", "joined": "2004" },
{ "id": "MT", "joined": "2004" },
{ "id": "PL", "joined": "2004" }
]
}, {
"name": "Joined in 2007",
"data": [
{ "id": "RO", "joined": "2007" },
{ "id": "BG", "joined": "2007" }
]
}, {
"name": "Joined in 2013",
"data": [
{ "id": "HR", "joined": "2013" }
]
}
];
// Create root and chart
var root = am5.Root.new("chartdiv");
// Set themes
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create chart
var chart = root.container.children.push(am5map.MapChart.new(root, {
minZoomLevel: 0.5, // zoom out to half the fitted size at most
// go to the home view once the map is fitted
autoHome: true,
homeZoomLevel: 3.5, // the home view is zoomed in on Europe...
homeGeoPoint: { longitude: 10, latitude: 52 } // ...centered on this point
}));
// Create series for the water: a faint fill behind the countries
// https://docs.amcharts.com/v5/charts/map-chart/map-polygon-series/#background-polygon
var waterSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
// the map fits the countries, not this rectangle around the whole world
affectsBounds: false
}));
waterSeries.mapPolygons.template.setAll({
fill: root.interfaceColors.get("alternativeBackground"), // dark on a light background, light on a dark one
fillOpacity: 0.05, // barely there
strokeOpacity: 0 // no outline
});
waterSeries.data.push({
geometry: am5map.getGeoRectangle(90, 180, -90, -180) // north, east, south and west edges: the whole world
});
// Create graticule series: grid lines every 10 degrees
// https://docs.amcharts.com/v5/charts/map-chart/graticule-series/
var graticuleSeries = chart.series.push(am5map.GraticuleSeries.new(root, {
step: 10
}));
graticuleSeries.mapLines.template.setAll({
stroke: root.interfaceColors.get("alternativeBackground"), // dark on a light background, light on a dark one
strokeOpacity: 0.08 // very faint
});
// Create world polygon series
var worldSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_worldLow,
exclude: ["AQ"] // no Antarctica
}));
// the other countries in a neutral gray that suits light and dark backgrounds: a solid color 30% of the way from
// the background color to the contrasting one, so a color picked for them shows as it is
worldSeries.mapPolygons.template.setAll({
fill: am5.Color.interpolate(0.3, root.interfaceColors.get("background"), root.interfaceColors.get("alternativeBackground"))
});
// Add legend
var legend = chart.children.push(am5.Legend.new(root, {
// plain square markers instead of markers that copy the look of the series
useDefaultMarker: true,
centerX: am5.p50, // the legend's middle...
x: am5.p50, // ...at the middle of the chart
centerY: am5.p100, // its bottom edge...
y: am5.p100, // ...at the chart's bottom...
dy: -20, // ...20px up from it
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 series for each group
var colors = am5.ColorSet.new(root, {
step: 2 // every other palette color...
});
colors.next(); // ...skipping the first one
am5.array.each(groupData, function(group) {
var countries = [];
var color = colors.next();
am5.array.each(group.data, function(country) {
countries.push(country.id)
});
var polygonSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_worldLow,
// only this group's countries, drawn over the gray world map
include: countries,
name: group.name,
fill: color // in the group's color
}));
polygonSeries.mapPolygons.template.setAll({
tooltipText: "[bold]{name}[/]\nMember since {joined}", // the name in bold, then the year it joined
interactive: true, // reacts to hover
fill: color,
strokeWidth: 1 // 1px borders
});
polygonSeries.mapPolygons.template.states.create("hover", {
fill: am5.Color.brighten(color, -0.3) // a darker shade of the group's color
});
// hovering one country highlights every country in its group
polygonSeries.mapPolygons.template.events.on("pointerover", function(ev) {
ev.target.series.mapPolygons.each(function(polygon) {
polygon.states.applyAnimate("hover");
});
});
polygonSeries.mapPolygons.template.events.on("pointerout", function(ev) {
ev.target.series.mapPolygons.each(function(polygon) {
polygon.states.applyAnimate("default");
});
});
polygonSeries.data.setAll(group.data);
legend.data.push(polygonSeries); // one legend item per group
});
{
"type": "MapChart",
"settings": {
"minZoomLevel": 0.5,
"autoHome": true,
"homeZoomLevel": 3.5,
"homeGeoPoint": {
"longitude": 10,
"latitude": 52
}
},
"properties": {
"series": [
"#series-0",
"#series-1",
"#series-2",
"#series-3",
"#series-4",
"#series-5",
"#series-6"
]
},
"children": [
{
"type": "Legend",
"settings": {
"useDefaultMarker": true,
"centerX": {
"type": "Percent",
"value": 50
},
"x": {
"type": "Percent",
"value": 50
},
"centerY": {
"type": "Percent",
"value": 100
},
"y": {
"type": "Percent",
"value": 100
},
"dy": -20,
"background": {
"type": "RoundedRectangle",
"settings": {
"fill": "@root.interfaceColors.get('background')",
"fillOpacity": 0.7
}
}
},
"properties": {
"data": [
"#series-3",
"#series-4",
"#series-5",
"#series-6"
],
"valueLabels": {
"properties": {
"template": {
"settings": {
"forceHidden": true
}
}
}
}
}
}
],
"refs": [
{
"data-0": [
{
"geometry": {
"type": "GeoRectangle",
"north": 90,
"east": 180,
"south": -90,
"west": -180
},
"__parse": true
}
]
},
{
"data-1": []
},
{
"data-2": []
},
{
"data-3": [
{
"id": "AT",
"joined": "1995",
"__parse": true
},
{
"id": "IE",
"joined": "1973",
"__parse": true
},
{
"id": "DK",
"joined": "1973",
"__parse": true
},
{
"id": "FI",
"joined": "1995",
"__parse": true
},
{
"id": "SE",
"joined": "1995",
"__parse": true
},
{
"id": "IT",
"joined": "1957",
"__parse": true
},
{
"id": "FR",
"joined": "1957",
"__parse": true
},
{
"id": "ES",
"joined": "1986",
"__parse": true
},
{
"id": "GR",
"joined": "1981",
"__parse": true
},
{
"id": "DE",
"joined": "1957",
"__parse": true
},
{
"id": "BE",
"joined": "1957",
"__parse": true
},
{
"id": "LU",
"joined": "1957",
"__parse": true
},
{
"id": "NL",
"joined": "1957",
"__parse": true
},
{
"id": "PT",
"joined": "1986",
"__parse": true
}
]
},
{
"data-4": [
{
"id": "LT",
"joined": "2004",
"__parse": true
},
{
"id": "LV",
"joined": "2004",
"__parse": true
},
{
"id": "CZ",
"joined": "2004",
"__parse": true
},
{
"id": "SK",
"joined": "2004",
"__parse": true
},
{
"id": "SI",
"joined": "2004",
"__parse": true
},
{
"id": "EE",
"joined": "2004",
"__parse": true
},
{
"id": "HU",
"joined": "2004",
"__parse": true
},
{
"id": "CY",
"joined": "2004",
"__parse": true
},
{
"id": "MT",
"joined": "2004",
"__parse": true
},
{
"id": "PL",
"joined": "2004",
"__parse": true
}
]
},
{
"data-5": [
{
"id": "RO",
"joined": "2007",
"__parse": true
},
{
"id": "BG",
"joined": "2007",
"__parse": true
}
]
},
{
"data-6": [
{
"id": "HR",
"joined": "2013",
"__parse": true
}
]
},
{
"series-0": {
"type": "MapPolygonSeries",
"settings": {
"affectsBounds": false
},
"properties": {
"data": "#data-0",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"fill": "@root.interfaceColors.get('alternativeBackground')",
"fillOpacity": 0.05,
"strokeOpacity": 0
}
}
}
}
}
}
},
{
"series-1": {
"type": "GraticuleSeries",
"settings": {
"step": 10
},
"properties": {
"mapLines": {
"properties": {
"template": {
"settings": {
"stroke": "@root.interfaceColors.get('alternativeBackground')",
"strokeOpacity": 0.08
}
}
}
}
}
}
},
{
"series-2": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow",
"exclude": [
"AQ"
]
},
"properties": {
"mapPolygons": {
"properties": {
"template": {
"settings": {
"fill": {
"type": "Color",
"value": "#b2b2b2"
}
}
}
}
}
}
}
},
{
"series-3": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow",
"include": [
"AT",
"IE",
"DK",
"FI",
"SE",
"IT",
"FR",
"ES",
"GR",
"DE",
"BE",
"LU",
"NL",
"PT"
],
"name": "Joined before 2004",
"fill": "@colors.getIndex(2)"
},
"properties": {
"data": "#data-3",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"tooltipText": "[bold]{name}[/]\nMember since {joined}",
"interactive": true,
"fill": "@colors.getIndex(2)",
"strokeWidth": 1
},
"states": [
{
"key": "hover",
"settings": {
"fill": {
"type": "Color",
"value": "#762263"
}
}
}
]
}
}
}
}
}
},
{
"series-4": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow",
"include": [
"LT",
"LV",
"CZ",
"SK",
"SI",
"EE",
"HU",
"CY",
"MT",
"PL"
],
"name": "Joined in 2004",
"fill": "@colors.getIndex(4)"
},
"properties": {
"data": "#data-4",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"tooltipText": "[bold]{name}[/]\nMember since {joined}",
"interactive": true,
"fill": "@colors.getIndex(4)",
"strokeWidth": 1
},
"states": [
{
"key": "hover",
"settings": {
"fill": {
"type": "Color",
"value": "#9f320b"
}
}
}
]
}
}
}
}
}
},
{
"series-5": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow",
"include": [
"RO",
"BG"
],
"name": "Joined in 2007",
"fill": "@colors.getIndex(1)"
},
"properties": {
"data": "#data-5",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"tooltipText": "[bold]{name}[/]\nMember since {joined}",
"interactive": true,
"fill": "@colors.getIndex(1)",
"strokeWidth": 1
},
"states": [
{
"key": "hover",
"settings": {
"fill": {
"type": "Color",
"value": "#492074"
}
}
}
]
}
}
}
}
}
},
{
"series-6": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow",
"include": [
"HR"
],
"name": "Joined in 2013",
"fill": "@colors.getIndex(3)"
},
"properties": {
"data": "#data-6",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"tooltipText": "[bold]{name}[/]\nMember since {joined}",
"interactive": true,
"fill": "@colors.getIndex(3)",
"strokeWidth": 1
},
"states": [
{
"key": "hover",
"settings": {
"fill": {
"type": "Color",
"value": "#90213a"
}
}
}
]
}
}
}
}
}
}
]
}
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.



