Location-Sensitive Map
A map that loads the visitor’s own country: it looks up your country from your IP address, then loads that country’s map with a random value for each region. Where the lookup can’t answer, it goes by your browser’s language setting.
About this map
When to localize a map
Opening on the visitor’s own country makes a map feel personal and saves them from hunting for it on a world map. It suits store finders, regional results and sales dashboards. Keep a way to switch countries, as an IP lookup can be wrong, for example behind a VPN.
Good for
- Store and dealer finders
- Regional results for each visitor
- Dashboards with data for each country
Think twice when
- Visitors comparing countries: show the world map
- Privacy-minded readers: say why you guess their country
- Exact locations: ask the browser, with the visitor’s permission
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:
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)
]);
// Colors from the theme, so the map follows the theme
var colors = am5.ColorSet.new(root, {});
// Create the map chart
// https://docs.amcharts.com/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 (the Albers USA projection can't turn)
projection: am5map.geoMercator(), // the starting projection; loadGeodata() may switch it
boxZoom: "shift", // hold Shift and drag to zoom into a box
layout: root.horizontalLayout, // the map and the heat legend side by side
// room at the top for the country's name
paddingTop: 36
}));
// 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, {
position: "absolute" // + and - zoom buttons over the map, left out of the side-by-side layout
}));
// the home button is hidden by default
zoomControl.homeButton.set("visible", true);
// Find the visitor's country from their IP address with amCharts' lookup service. The service only answers pages
// on amcharts.com, so anywhere else (or if it fails) the map falls back to the country in the browser's language
// setting, such as "US" in "en-US".
am5.net.load("https://www.amcharts.com/tools/country/?v=xz6Z", chart).then(function (result) {
var geo = am5.JSONParser.parse(result.response);
loadGeodata(geo.country_code);
}).catch(function () {
var region = (navigator.language || "").split("-")[1];
loadGeodata(region ? region.toUpperCase() : "US");
});
// Create polygon series for the country's regions, filled by value
// https://docs.amcharts.com/v5/charts/map-chart/map-polygon-series/
var polygonSeries = chart.series.push(am5map.MapPolygonSeries.new(root, {
// works out the lowest and highest value, which the heat rules and the legend use
calculateAggregates: true,
valueField: "value"
}));
polygonSeries.mapPolygons.template.setAll({
tooltipText: "{name}: {value}", // the region's name and value on hover
interactive: true // reacts to the pointer, for the hover color below
});
polygonSeries.mapPolygons.template.states.create("hover", {
fill: colors.getIndex(9) // the hovered region turns another theme color
});
// the regions are shaded from light to dark by value
polygonSeries.set("heatRules", [{
target: polygonSeries.mapPolygons.template,
dataField: "value",
min: am5.Color.lighten(colors.getIndex(0), 0.6), // the lowest value: a light shade of the first color...
max: am5.Color.brighten(colors.getIndex(0), -0.5), // ...the highest: a dark one
key: "fill" // the rule sets the fill
}]);
// hovering a region marks its value on the heat legend
polygonSeries.mapPolygons.template.events.on("pointerover", function(ev) {
heatLegend.showValue(ev.target.dataItem.get("value"));
});
// loads the regions map of a country (by its two-letter code) with random values
function loadGeodata(country) {
// The country's map, or the United States where there is no map for the country
var countryData = am5geodata_data_countries2[country];
if (!countryData || !countryData.maps.length) {
country = "US";
countryData = am5geodata_data_countries2.US;
}
// The Albers USA projection puts Alaska and Hawaii next to the other states
if (country == "US") {
chart.set("projection", am5map.geoAlbersUsa());
}
else {
chart.set("projection", am5map.geoMercator());
}
// Load the map and give each region a random value
am5.net.load("https://cdn.amcharts.com/lib/5/geodata/json/" + countryData.maps[0] + ".json", chart).then(function (result) {
var geodata = am5.JSONParser.parse(result.response);
var data = [];
for (var i = 0; i < geodata.features.length; i++) {
data.push({
id: geodata.features[i].id,
value: Math.round(Math.random() * 10000) // a random value up to 10,000
});
}
polygonSeries.set("geoJSON", geodata); // the regions' shapes
polygonSeries.data.setAll(data);
});
// Country name above the map: "absolute" keeps it out of the layout that puts the map and heat legend side by side
chart.children.push(am5.Label.new(root, {
position: "absolute",
x: 0, // the top left corner
y: 0,
fontSize: 20, // larger text
text: countryData.country // the country's name from the countries list
}));
}
// a color scale beside the map, in the same colors as the heat rules
var heatLegend = chart.children.push(
am5.HeatLegend.new(root, {
orientation: "vertical", // standing upright
startColor: am5.Color.lighten(colors.getIndex(0), 0.6), // the lowest color...
endColor: am5.Color.brighten(colors.getIndex(0), -0.5), // ...and the highest, the same as in the heat rules
startText: "Lowest", // words at the ends instead of numbers
endText: "Highest",
stepCount: 5 // five blocks of color instead of a smooth gradient
})
);
// the zoom buttons keep to the left of the heat legend
heatLegend.events.on("boundschanged", function () {
zoomControl.set("dx", -heatLegend.width());
});
// smaller labels on the heat legend
heatLegend.startLabel.setAll({
fontSize: 12
});
heatLegend.endLabel.setAll({
fontSize: 12
});
// the legend runs from the lowest value to the highest
polygonSeries.events.on("datavalidated", function () {
heatLegend.set("startValue", polygonSeries.getPrivate("valueLow"));
heatLegend.set("endValue", polygonSeries.getPrivate("valueHigh"));
});
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.




