One map, two layers: a polygon series of world countries, and a second one of US states drawn on top in a color of its own.
A map chart can stack any number of polygon series, each from its own geodata, with its own colors, tooltips and events. That is how a world map gets state-level detail for one country without loading states for all of them. The layers stay separate, so one can be hidden, restyled or given data of its own.
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.
npm install @amcharts/amcharts5 and @amcharts/amcharts5-geodata. See Getting started.
The same chart as a JSON config. Map 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."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://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create the map chart
// https://www.amcharts.com/docs/v5/charts/map-chart/
var chart = 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: "translateX", // dragging moves the map sideways...
panY: "translateY", // ...and up and down
boxZoom: "shift", // hold Shift and drag to zoom into a box
projection: am5map.geoEqualEarth() // a projection that keeps the countries' areas true
}));
// Create series for the water: a faint fill behind the countries
// https://www.amcharts.com/docs/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"), // the color that contrasts with the background...
fillOpacity: 0.05, // ...barely there
strokeOpacity: 0 // no outline
});
waterSeries.data.push({
geometry: am5map.getGeoRectangle(90, 180, -90, -180) // a rectangle over the whole globe
});
// Create graticule series: grid lines every 10 degrees
// https://www.amcharts.com/docs/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"), // contrasting with the background...
strokeOpacity: 0.08 // ...and very faint
});
// Create main polygon series for countries
// https://www.amcharts.com/docs/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 on hover
// a click switches the "active" state on or off, which keeps the country highlighted
toggleKey: "active",
interactive: true // reacts to the pointer and to clicks
});
polygonSeries.mapPolygons.template.states.create("hover", {
fill: root.interfaceColors.get("primaryButtonHover") // the theme's button hover color
});
polygonSeries.mapPolygons.template.states.create("active", {
fill: root.interfaceColors.get("primaryButtonHover") // the same color while active
});
// US Series
// Create a polygon series for the US states
// https://www.amcharts.com/docs/v5/charts/map-chart/map-polygon-series/
var polygonSeriesUS = chart.series.push(am5map.MapPolygonSeries.new(root, {
// the states, added after the world, so they draw over its United States
geoJSON: am5geodata_usaLow
}));
polygonSeriesUS.mapPolygons.template.setAll({
tooltipText: "{name}", // the state's name on hover
toggleKey: "active", // a click keeps the state highlighted
interactive: true // reacts to the pointer and to clicks
});
var colors = am5.ColorSet.new(root, {}); // the theme's colors
polygonSeriesUS.mapPolygons.template.set("fill", colors.getIndex(3)); // the states in another theme color
polygonSeriesUS.mapPolygons.template.states.create("hover", {
fill: root.interfaceColors.get("primaryButtonHover") // the theme's button hover color
});
polygonSeriesUS.mapPolygons.template.states.create("active", {
fill: root.interfaceColors.get("primaryButtonHover") // the same color while active
});
// Add zoom control
// https://www.amcharts.com/docs/v5/charts/map-chart/map-pan-zoom/#Zoom_control
var zoomControl = chart.set("zoomControl", am5map.ZoomControl.new(root, {})); // + and - zoom buttons
zoomControl.homeButton.set("visible", true); // and a home button, hidden by default
// Set clicking on "water" to zoom out
chart.chartContainer.get("background").events.on("click", function () {
chart.goHome();
})
// Make stuff animate on load
chart.appear(1000, 100);
