This map demonstrates loading data from two sources: the polygons are loaded from a GeoJSON file and the data values come from a live query to the US Census API. You can use the controls above the map to select a category of data to display (the "census variable"). The display is then updated to show a choropleth map shading the various US regions in proportion to the values recorded in the census.
How it works
When the map loads, it first loads a GeoJSON file containing polygons
defining the US state boundaries and render them using the
loadGeoJson
method. The controls on the map are used to select a data source and
then execute a query against the
US Census Data API for the
specified variable.
The only trick in the code below is setting the
idPropertyName
for the data that is loaded. When we load the Census data we need a way
to connect it with the shape data based on some common key. In this
case we're using the 'STATE' property defined in both the Census data
and in the GeoJSON properties.
function loadMapShapes() {
map.data.loadGeoJson('states.json', { idPropertyName: 'STATE' });
}
Importing data from the US Census API
The US Census Bureau provides an API for querying data in a number of
ways. This document does not describe the Census API, other than to say
that the data is returned in JSON format. We use the state ID, provided in
the 2nd column, to look up the existing state data (using the
lookupId method of google.maps.Data) and update
with the census data (using the setProperty method of google.maps.Data)
function loadCensusData(variable) {
// load the requested variable from the census API
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.census.gov/data/2012/acs5/profile?get=' +
variable + '&for=state:*&key=YOUR_API_KEY');
xhr.onload = function() {
var censusData = JSON.parse(xhr.responseText);
censusData.shift(); // the first row contains column names
censusData.forEach(function(row) {
var censusVariable = parseFloat(row[0]);
var stateId = row[1];
// keep track of min and max values
if (censusVariable < censusMin) {
censusMin = censusVariable;
}
if (censusVariable > censusMax) {
censusMax = censusVariable;
}
// update the existing row with the new data
map.data
.getFeatureById(stateId)
.setProperty('census_variable', censusVariable);
});
// update and display the legend
document.getElementById('census-min').textContent =
censusMin.toLocaleString();
document.getElementById('census-max').textContent =
censusMax.toLocaleString();
};
xhr.send();
}
Styling the data
Data can be styled through the use of a Data.StyleOptions
object or through a function that returns a Data.StyleOptions
object. Here we create a choropleth map by applying a gradient to each
polygon in the dataset based on the value in the census data.
// set up the style rules and events for google.maps.Data
map.data.setStyle(styleFeature);
function styleFeature(feature) {
var low = [5, 69, 54]; // color of smallest datum
var high = [151, 83, 34]; // color of largest datum
// delta represents where the value sits between the min and max
var delta = (feature.getProperty('census_variable') - censusMin) /
(censusMax - censusMin);
var color = [];
for (var i = 0; i < 3; i++) {
// calculate an integer color based on the delta
color[i] = (high[i] - low[i]) * delta + low[i];
}
// determine whether to show this shape or not
var showRow = true;
if (feature.getProperty('census_variable') == null ||
isNaN(feature.getProperty('census_variable'))) {
showRow = false;
}
var outlineWeight = 0.5, zIndex = 1;
if (feature.getProperty('state') === 'hover') {
outlineWeight = zIndex = 2;
}
return {
strokeWeight: outlineWeight,
strokeColor: '#fff',
zIndex: zIndex,
fillColor: 'hsl(' + color[0] + ',' + color[1] + '%,' + color[2] + '%)',
fillOpacity: 0.75,
visible: showRow
};
}
In addition to the coloring, we have created an interactive element by adding events that respond to mouse activity. When you hover your mouse cursor (or finger) over a region with data, the border becomes heavier and the data card is updated with the value being touched.
// set up the style rules and events for google.maps.Data
map.data.addListener('mouseover', mouseInToRegion);
map.data.addListener('mouseout', mouseOutOfRegion);
/**
* Responds to the mouse-in event on a map shape (state).
*
* @param {?google.maps.MouseEvent} e
*/
function mouseInToRegion(e) {
// set the hover state so the setStyle function can change the border
e.feature.setProperty('state', 'hover');
var percent = (e.feature.getProperty('census_variable') - censusMin) /
(censusMax - censusMin) * 100;
// update the label
document.getElementById('data-label').textContent =
e.feature.getProperty('NAME');
document.getElementById('data-value').textContent =
e.feature.getProperty('census_variable').toLocaleString();
document.getElementById('data-box').style.display = 'block';
document.getElementById('data-caret').style.display = 'block';
document.getElementById('data-caret').style.paddingLeft = percent + '%';
}
/**
* Responds to the mouse-out event on a map shape (state).
*
* @param {?google.maps.MouseEvent} e
*/
function mouseOutOfRegion(e) {
// reset the hover state, returning the border to normal
e.feature.setProperty('state', 'normal');
}
This demo uses the Census Bureau Data API but is not endorsed or certified by the Census Bureau.
