Zooming to Countries Map
A world map that zooms to any country you click. Click the country again, or the sea, to zoom back out.
About this map
When click-to-zoom helps
A world map fits every country on one screen, but small ones end up a few pixels wide. Zooming to the country a reader picks lets one map be the overview and the close-up, with no second map to load. It suits maps people explore more than maps they read at a glance.
Good for
- Pickers: choose a country, see it up close
- World overviews with small countries to reach
- Maps that lead on to details per country
Think twice when
- Regions inside the country: a drill-down map loads them
- Comparing countries: color them by value instead
- Print and static reports: zooming needs a reader
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.
// 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 the map chart
// https://docs.amcharts.com/v5/charts/map-chart/
var chart = root.container.children.push(am5map.MapChart.new(root, {
// near-black space behind the satellite picture, shown only with it
background: am5.Rectangle.new(root, {
fill: am5.color(0x101318),
fillOpacity: 0 // invisible until the satellite view turns it on
}),
// go to the home view once the map is fitted
autoHome: true,
panX: "translateX", // drag the map to move it sideways...
panY: "translateY", // ...and up and down
// hold Shift and drag to zoom into the area you draw
boxZoom: "shift",
minZoomLevel: 0.5, // the map can zoom out to half its fitted size
projection: am5map.geoEqualEarth() // equal-area: countries keep their true relative size
}));
// Create series for the ocean
// https://docs.amcharts.com/v5/charts/map-chart/map-polygon-series/#background-polygon
var oceanSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {}));
oceanSeries.mapPolygons.template.setAll({
fill: root.interfaceColors.get("alternativeBackground"), // the theme's contrast color...
fillOpacity: 0.05, // ...at 5%, a faint tint
strokeOpacity: 0 // no outline
});
oceanSeries.data.push({
geometry: am5map.getGeoRectangle(90, 180, -90, -180) // north, east, south and west edges: the whole world
});
// Satellite view: NASA's picture of the Earth by day, under the grid lines and the countries. Hidden at first
// (visible: false): make it visible for the satellite view
// https://docs.amcharts.com/v5/charts/map-chart/map-raster-series/
var satelliteSeries = chart.series.push(am5map.MapRasterSeries.new(root, {
visible: false,
// the map fits the countries, not the whole picture
affectsBounds: false
}));
// Create graticule series
// https://docs.amcharts.com/v5/charts/map-chart/graticule-series/
var graticuleSeries = chart.series.push(am5map.GraticuleSeries.new(root, {
step: 10 // a line every 10 degrees
}));
graticuleSeries.mapLines.template.setAll({
stroke: root.interfaceColors.get("alternativeBackground"), // the theme's contrast color...
strokeOpacity: 0.08 // ...very faint
});
// Create main polygon series for countries
// https://docs.amcharts.com/v5/charts/map-chart/map-polygon-series/
var polygonSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_worldLow // the world's countries, in low detail
}));
polygonSeries.mapPolygons.template.setAll({
tooltipText: "{name}", // the country's name from the map data
// a click turns the country's "active" state on or off, which the code below zooms on
toggleKey: "active",
interactive: true // the countries react to the mouse
});
// Hover and active fill the country; over the satellite picture they turn to a bright outline instead (see below)
polygonSeries.mapPolygons.template.states.create("hover", {
fill: root.interfaceColors.get("primaryButtonHover"), // the theme's hover color for buttons
fillOpacity: 1
});
// The selected country stays highlighted
polygonSeries.mapPolygons.template.states.create("active", {
fill: root.interfaceColors.get("primaryButtonActive"), // the theme's color for a switched-on button
fillOpacity: 1
});
// Zoom to the country that was clicked, and back out when it's clicked again
var previousPolygon;
polygonSeries.mapPolygons.template.on("active", function (active, target) {
if (previousPolygon && previousPolygon != target) {
previousPolygon.set("active", false); // only one country selected at a time
}
if (target.get("active")) {
polygonSeries.zoomToDataItem(target.dataItem); // zoom in until the country fills the view
}
else {
chart.goHome(); // back to the whole map
}
previousPolygon = target;
});
// Add zoom control
// https://docs.amcharts.com/v5/charts/map-chart/map-pan-zoom/#zoom-control
var zoomControl = chart.set("zoomControl", am5map.ZoomControl.new(root, {}));
zoomControl.homeButton.set("visible", true); // a button that goes back to the home view
// Set clicking on "water" to zoom out
chart.chartContainer.get("background").events.on("click", function () {
chart.goHome();
});
// The image credit
var credit = chart.children.push(am5.Label.new(root, {
text: "Imagery: NASA Earth Observatory",
fontSize: 12, // in pixels
fill: am5.color(0xffffff), // white, over the dark satellite picture
fillOpacity: 0.6, // slightly faded
x: am5.p100, // at the right edge...
centerX: am5.p100,
dx: -10, // ...10px in from it
y: 10, // 10px from the top
visible: false // shown only with the satellite view
}));
// The countries' own look, to go back to
var landTemplate = polygonSeries.mapPolygons.template;
var landLook = {
fillOpacity: landTemplate.get("fillOpacity", 1),
stroke: landTemplate.get("stroke", root.interfaceColors.get("background")),
strokeOpacity: landTemplate.get("strokeOpacity", 1)
};
// Hovered and active countries: their own look on the map, only a bright outline over the satellite picture
var outlineLook = { fillOpacity: 0, strokeOpacity: 1, strokeWidth: 2 };
var hoverState = landTemplate.states.lookup("hover");
var hoverLook = stateLook(hoverState);
var activeState = landTemplate.states.lookup("active");
var activeLook = stateLook(activeState);
// the settings of a state that the outline changes, as they are on the map
function stateLook(state) {
return {
fillOpacity: state.get("fillOpacity", landLook.fillOpacity),
strokeOpacity: state.get("strokeOpacity", landLook.strokeOpacity),
strokeWidth: state.get("strokeWidth", landTemplate.get("strokeWidth", 1))
};
}
// The picture loads the first time it shows. Then the countries turn to white outlines over it, the grid lines
// turn white, the credit shows and the map sits in near-black space
satelliteSeries.on("visible", function(visible) {
if (visible) {
satelliteSeries.set("src", "https://cdn.amcharts.com/lib/5/geodata/images/earthDay2048.jpg");
}
credit.set("visible", visible);
chart.get("background").set("fillOpacity", visible ? 1 : 0);
var look = visible ? { fillOpacity: 0, stroke: am5.color(0xffffff), strokeOpacity: 0.6 } : landLook;
landTemplate.setAll(look);
hoverState.setAll(visible ? outlineLook : hoverLook);
activeState.setAll(visible ? outlineLook : activeLook);
// a country hovered before kept the look it had then as its own and as its default one: give it the new look
polygonSeries.mapPolygons.each(function (polygon) {
var defaultState = polygon.states.lookup("default");
if (defaultState) {
defaultState.setAll(look);
}
polygon.setAll(polygon.get("active") ? (visible ? outlineLook : activeLook) : look);
});
graticuleSeries.mapLines.template.set("stroke", visible ? am5.color(0xffffff) : root.interfaceColors.get("alternativeBackground"));
});
// Make stuff animate on load
chart.appear(1000, 100);
{
"type": "MapChart",
"settings": {
"background": {
"type": "Rectangle",
"settings": {
"fill": {
"type": "Color",
"value": "#101318"
},
"fillOpacity": 0
}
},
"autoHome": true,
"panX": "translateX",
"panY": "translateY",
"boxZoom": "shift",
"minZoomLevel": 0.5,
"zoomControl": {
"type": "ZoomControl",
"properties": {
"homeButton": {
"settings": {
"visible": true
}
}
}
},
"projectionName": "geoEqualEarth"
},
"properties": {
"series": [
"#series-0",
"#series-1",
"#series-2",
"#series-3"
]
},
"children": [
{
"type": "Label",
"settings": {
"text": "Imagery: NASA Earth Observatory",
"fontSize": 12,
"fill": {
"type": "Color",
"value": "#ffffff"
},
"fillOpacity": 0.6,
"x": {
"type": "Percent",
"value": 100
},
"centerX": {
"type": "Percent",
"value": 100
},
"dx": -10,
"y": 10,
"visible": false
},
"index": 2
}
],
"refs": [
{
"data-0": [
{
"geometry": {
"type": "GeoRectangle",
"north": 90,
"east": 180,
"south": -90,
"west": -180
},
"__parse": true
}
]
},
{
"data-1": []
},
{
"data-2": []
},
{
"series-0": {
"type": "MapPolygonSeries",
"properties": {
"data": "#data-0",
"mapPolygons": {
"properties": {
"template": {
"settings": {
"fill": "@root.interfaceColors.get('alternativeBackground')",
"fillOpacity": 0.05,
"strokeOpacity": 0
}
}
}
}
}
}
},
{
"series-1": {
"type": "MapRasterSeries",
"settings": {
"visible": false,
"affectsBounds": false
}
}
},
{
"series-2": {
"type": "GraticuleSeries",
"settings": {
"step": 10
},
"properties": {
"mapLines": {
"properties": {
"template": {
"settings": {
"stroke": "@root.interfaceColors.get('alternativeBackground')",
"strokeOpacity": 0.08
}
}
}
}
}
}
},
{
"series-3": {
"type": "MapPolygonSeries",
"settings": {
"geoJSON": "am5geodata_worldLow"
},
"properties": {
"mapPolygons": {
"properties": {
"template": {
"settings": {
"tooltipText": "{name}",
"toggleKey": "active",
"interactive": true
},
"states": [
{
"key": "hover",
"settings": {
"fill": "@root.interfaceColors.get('primaryButtonHover')",
"fillOpacity": 1
}
},
{
"key": "active",
"settings": {
"fill": "@root.interfaceColors.get('primaryButtonActive')",
"fillOpacity": 1
}
}
]
}
}
}
}
}
}
]
}
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.
Go further in the Dojo.
Full apps and games built with amCharts 5.





