The Google Maps Data layer provides a container for arbitrary geospatial data. You can use the Data layer to store your custom data, or to display GeoJSON data on a Google map.
Overview
Watch this DevBytes video to learn more about the Data Layer.
With the Maps JavaScript API you can mark up a map with a
variety of overlays, such as markers, polylines, polygons, etc. Each of these
annotations combines styling information with location data. The
google.maps.Data
class is a container for arbitrary geospatial data. Instead
of adding these overlays, you can use the Data layer to add arbitrary
geographical data to your map. If that data contains geometries, such as points,
lines or polygons, the API will render these by default as markers, polylines
and polygons. You can style these features as you would a normal overlay, or
apply styling rules based on other properties contained in your data set.
The google.maps.Data
class allows you to:
- Draw polygons on your map.
- Add GeoJSON data to your map.
GeoJSON is a standard for geospatial data on the internet. TheData
class follows the structure of GeoJSON in its data representation and makes it easy to display GeoJSON data. Use theloadGeoJson()
method to easily import GeoJSON data and display points, line-strings and polygons. - Use
google.maps.Data
to model arbitrary data.
Most real-world entities have other properties associated with them. For example, stores have opening hours, roads have traffic speed, and each Girl Guide troupe has cookie-selling turf. Withgoogle.maps.Data
, you can model these properties, and style your data accordingly. - Choose how your data is represented, and change
your mind on the fly.
The Data layer lets you make decisions about the visualization and interaction of your data. For example, when looking at a map of convenience stores you might choose to display only those stores that sell transit tickets.
Draw a polygon
The Data.Polygon
class handles polygon winding for you. You can pass it an array of one or more
linear rings, defined as latitude/longitude coordinates. The first linear ring
defines the outer boundary of the polygon. If you pass more than one linear
ring, the second and subsequent linear rings are used to define inner paths
(holes) in the polygon.
The following example creates a rectangular polygon with two holes in it:
TypeScript
// This example uses the Google Maps JavaScript API's Data layer // to create a rectangular polygon with 2 holes in it. function initMap(): void { const map = new google.maps.Map( document.getElementById("map") as HTMLElement, { zoom: 6, center: { lat: -33.872, lng: 151.252 }, } ); // Define the LatLng coordinates for the outer path. const outerCoords = [ { lat: -32.364, lng: 153.207 }, // north west { lat: -35.364, lng: 153.207 }, // south west { lat: -35.364, lng: 158.207 }, // south east { lat: -32.364, lng: 158.207 }, // north east ]; // Define the LatLng coordinates for an inner path. const innerCoords1 = [ { lat: -33.364, lng: 154.207 }, { lat: -34.364, lng: 154.207 }, { lat: -34.364, lng: 155.207 }, { lat: -33.364, lng: 155.207 }, ]; // Define the LatLng coordinates for another inner path. const innerCoords2 = [ { lat: -33.364, lng: 156.207 }, { lat: -34.364, lng: 156.207 }, { lat: -34.364, lng: 157.207 }, { lat: -33.364, lng: 157.207 }, ]; map.data.add({ geometry: new google.maps.Data.Polygon([ outerCoords, innerCoords1, innerCoords2, ]), }); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
// This example uses the Google Maps JavaScript API's Data layer // to create a rectangular polygon with 2 holes in it. function initMap() { const map = new google.maps.Map(document.getElementById("map"), { zoom: 6, center: { lat: -33.872, lng: 151.252 }, }); // Define the LatLng coordinates for the outer path. const outerCoords = [ { lat: -32.364, lng: 153.207 }, // north west { lat: -35.364, lng: 153.207 }, // south west { lat: -35.364, lng: 158.207 }, // south east { lat: -32.364, lng: 158.207 }, // north east ]; // Define the LatLng coordinates for an inner path. const innerCoords1 = [ { lat: -33.364, lng: 154.207 }, { lat: -34.364, lng: 154.207 }, { lat: -34.364, lng: 155.207 }, { lat: -33.364, lng: 155.207 }, ]; // Define the LatLng coordinates for another inner path. const innerCoords2 = [ { lat: -33.364, lng: 156.207 }, { lat: -34.364, lng: 156.207 }, { lat: -34.364, lng: 157.207 }, { lat: -33.364, lng: 157.207 }, ]; map.data.add({ geometry: new google.maps.Data.Polygon([ outerCoords, innerCoords1, innerCoords2, ]), }); } window.initMap = initMap;
Load GeoJSON
GeoJSON is a common standard for sharing geospatial data on the internet. It is lightweight and easily human-readable, making it ideal for sharing and collaborating. With the Data layer, you can add GeoJSON data to a Google map in just one line of code.
map.data.loadGeoJson('google.json');
Every map has a map.data
object, which acts as a data layer for arbitrary geospatial data, including
GeoJSON. You can load and display a GeoJSON file by calling the loadGeoJSON()
method of the data
object. The below example shows how to add a map and load
external GeoJSON data.
TypeScript
let map: google.maps.Map; function initMap(): void { map = new google.maps.Map(document.getElementById("map") as HTMLElement, { zoom: 4, center: { lat: -28, lng: 137 }, }); // NOTE: This uses cross-domain XHR, and may not work on older browsers. map.data.loadGeoJson( "https://storage.googleapis.com/mapsdevsite/json/google.json" ); } declare global { interface Window { initMap: () => void; } } window.initMap = initMap;
JavaScript
let map; function initMap() { map = new google.maps.Map(document.getElementById("map"), { zoom: 4, center: { lat: -28, lng: 137 }, }); // NOTE: This uses cross-domain XHR, and may not work on older browsers. map.data.loadGeoJson( "https://storage.googleapis.com/mapsdevsite/json/google.json", ); } window.initMap = initMap;
Try Sample
Sample GeoJSON
Most of the examples on this page use a common GeoJSON file. This file defines the six characters in ‘Google’ as polygons over Australia. Please feel free to copy or modify this file as you test out the Data layer.
Note: In order to load a json file from another domain, that domain must have enabled Cross-origin resource sharing.
The full text of the file can be seen below by expanding the small arrow next to the words google.json.
google.json
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "letter": "G", "color": "blue", "rank": "7", "ascii": "71" }, "geometry": { "type": "Polygon", "coordinates": [ [ [123.61, -22.14], [122.38, -21.73], [121.06, -21.69], [119.66, -22.22], [119.00, -23.40], [118.65, -24.76], [118.43, -26.07], [118.78, -27.56], [119.22, -28.57], [120.23, -29.49], [121.77, -29.87], [123.57, -29.64], [124.45, -29.03], [124.71, -27.95], [124.80, -26.70], [124.80, -25.60], [123.61, -25.64], [122.56, -25.64], [121.72, -25.72], [121.81, -26.62], [121.86, -26.98], [122.60, -26.90], [123.57, -27.05], [123.57, -27.68], [123.35, -28.18], [122.51, -28.38], [121.77, -28.26], [121.02, -27.91], [120.49, -27.21], [120.14, -26.50], [120.10, -25.64], [120.27, -24.52], [120.67, -23.68], [121.72, -23.32], [122.43, -23.48], [123.04, -24.04], [124.54, -24.28], [124.58, -23.20], [123.61, -22.14] ] ] } }, { "type": "Feature", "properties": { "letter": "o", "color": "red", "rank": "15", "ascii": "111" }, "geometry": { "type": "Polygon", "coordinates": [ [ [128.84, -25.76], [128.18, -25.60], [127.96, -25.52], [127.88, -25.52], [127.70, -25.60], [127.26, -25.79], [126.60, -26.11], [126.16, -26.78], [126.12, -27.68], [126.21, -28.42], [126.69, -29.49], [127.74, -29.80], [128.80, -29.72], [129.41, -29.03], [129.72, -27.95], [129.68, -27.21], [129.33, -26.23], [128.84, -25.76] ], [ [128.45, -27.44], [128.32, -26.94], [127.70, -26.82], [127.35, -27.05], [127.17, -27.80], [127.57, -28.22], [128.10, -28.42], [128.49, -27.80], [128.45, -27.44] ] ] } }, { "type": "Feature", "properties": { "letter": "o", "color": "yellow", "rank": "15", "ascii": "111" }, "geometry": { "type": "Polygon", "coordinates": [ [ [131.87, -25.76], [131.35, -26.07], [130.95, -26.78], [130.82, -27.64], [130.86, -28.53], [131.26, -29.22], [131.92, -29.76], [132.45, -29.87], [133.06, -29.76], [133.72, -29.34], [134.07, -28.80], [134.20, -27.91], [134.07, -27.21], [133.81, -26.31], [133.37, -25.83], [132.71, -25.64], [131.87, -25.76] ], [ [133.15, -27.17], [132.71, -26.86], [132.09, -26.90], [131.74, -27.56], [131.79, -28.26], [132.36, -28.45], [132.93, -28.34], [133.15, -27.76], [133.15, -27.17] ] ] } }, { "type": "Feature", "properties": { "letter": "g", "color": "blue", "rank": "7", "ascii": "103" }, "geometry": { "type": "Polygon", "coordinates": [ [ [138.12, -25.04], [136.84, -25.16], [135.96, -25.36], [135.26, -25.99], [135, -26.90], [135.04, -27.91], [135.26, -28.88], [136.05, -29.45], [137.02, -29.49], [137.81, -29.49], [137.94, -29.99], [137.90, -31.20], [137.85, -32.24], [136.88, -32.69], [136.45, -32.36], [136.27, -31.80], [134.95, -31.84], [135.17, -32.99], [135.52, -33.43], [136.14, -33.76], [137.06, -33.83], [138.12, -33.65], [138.86, -33.21], [139.30, -32.28], [139.30, -31.24], [139.30, -30.14], [139.21, -28.96], [139.17, -28.22], [139.08, -27.41], [139.08, -26.47], [138.99, -25.40], [138.73, -25.00 ], [138.12, -25.04] ], [ [137.50, -26.54], [136.97, -26.47], [136.49, -26.58], [136.31, -27.13], [136.31, -27.72], [136.58, -27.99], [137.50, -28.03], [137.68, -27.68], [137.59, -26.78], [137.50, -26.54] ] ] } }, { "type": "Feature", "properties": { "letter": "l", "color": "green", "rank": "12", "ascii": "108" }, "geometry": { "type": "Polygon", "coordinates": [ [ [140.14,-21.04], [140.31,-29.42], [141.67,-29.49], [141.59,-20.92], [140.14,-21.04] ] ] } }, { "type": "Feature", "properties": { "letter": "e", "color": "red", "rank": "5", "ascii": "101" }, "geometry": { "type": "Polygon", "coordinates": [ [ [144.14, -27.41], [145.67, -27.52], [146.86, -27.09], [146.82, -25.64], [146.25, -25.04], [145.45, -24.68], [144.66, -24.60], [144.09, -24.76], [143.43, -25.08], [142.99, -25.40], [142.64, -26.03], [142.64, -27.05], [142.64, -28.26], [143.30, -29.11], [144.18, -29.57], [145.41, -29.64], [146.46, -29.19], [146.64, -28.72], [146.82, -28.14], [144.84, -28.42], [144.31, -28.26], [144.14, -27.41] ], [ [144.18, -26.39], [144.53, -26.58], [145.19, -26.62], [145.72, -26.35], [145.81, -25.91], [145.41, -25.68], [144.97, -25.68], [144.49, -25.64], [144, -25.99], [144.18, -26.39] ] ] } } ] }
Style GeoJSON Data
Use the Data.setStyle()
method to specify how your data should look. The
setStyle()
method takes either a
StyleOptions
object literal, or a function that computes the style for each feature.
Simple style rules
The simplest way to style features is to pass a StyleOptions
object literal
to setStyle()
. This will set a single style for each feature in your
collection. Note that each feature type is only able to render a subset of the
available options. This means that its possible to combine styles for different
feature types in a single object literal. For example, the below snippet sets
both a custom icon
, which only affects point geometries, and fillColor
,
which only affects polygons.
map.data.setStyle({ icon: '//example.com/path/to/image.png', fillColor: 'green' });
More information on valid style/feature combinations can be found in Style Options.
Below is an example of setting the stroke and fill color for several features
using a StyleOptions
object literal. Notice that each polygon is styled the
same.
// Set the stroke width, and fill color for each polygon map.data.setStyle({ fillColor: 'green', strokeWeight: 1 });
Declarative style rules
If you want to update the style of a large number of overlays, such as markers or polylines, you typically have to iterate through each overlay on your map and set its style individually. With the Data layer, you can set rules declaratively and they will be applied across your entire data set. When either the data, or the rules, are updated, the styling will be automatically applied to every feature. You can use a features properties to customize its style.
For example, the below code sets the color of each character in our
google.json
by examining its position in the ascii character set. In this case
we’ve encoded the character position along with our data.
// Color Capital letters blue, and lower case letters red. // Capital letters are represented in ascii by values less than 91 map.data.setStyle(function(feature) { var ascii = feature.getProperty('ascii'); var color = ascii > 91 ? 'red' : 'blue'; return { fillColor: color, strokeWeight: 1 }; });
Remove styles
If you’d like to remove any applied styles, pass an empty object literal to the
setStyles()
method.
// Remove custom styles. map.data.setStyle({});
This will remove any custom styles that you’ve specified, and the features will
render using the default styles. If you’d instead like to no longer render the
features, set the visible
property of StyleOptions
to false
.
// Hide the Data layer. map.data.setStyle({visible: false});
Override default styles
Styling rules are typically applied to every feature in the Data layer. However, there are times when you’d like to apply special styling rules to specific features. For example, as a way to highlight a feature on click.
To apply special styling rules, use the overrideStyle()
method. Any properties
that you change with the overrideStyle()
method are applied in addition to the
global styles already specified in setStyle()
. For example, the below code
will change the fill color of a polygon on click, but will not set any other
styles.
// Set the global styles. map.data.setStyle({ fillColor: 'green', strokeWeight: 3 }); // Set the fill color to red when the feature is clicked. // Stroke weight remains 3. map.data.addListener('click', function(event) { map.data.overrideStyle(event.feature, {fillColor: 'red'}); });
Call the revertStyle()
method to remove all style overrides.
Style options
The options available for styling each feature depend upon the feature type.
For example, fillColor
will only render on polygon geometries, while icon
will only appear on a point geometry. More information is available in the
reference documentation for
StyleOptions
.
Available on all geometries
clickable
: Iftrue
, the feature receives mouse and touch eventsvisible
: Iftrue
, the feature is visible.zIndex
: All features are displayed on the map in order of theirzIndex
, with higher values displaying in front of features with lower values. Markers are always displayed in front of line-strings and polygons.
Available on point geometries
cursor
: Mouse cursor to show on hover.icon
: Icon to show for the point geometry.shape
: Defines the image map used for hit detection.title
: Rollover text.
Available on line geometries
strokeColor
: The stroke color. All CSS3 colors are supported except for extended named colors.strokeOpacity
: The stroke opacity between 0.0 and 1.0.strokeWeight
: The stroke width in pixels.
Available on polygon geometries
fillColor
: The fill color. All CSS3 colors are supported except for extended named colors.fillOpacity
: The fill opacity between0.0
and1.0.
strokeColor
: The stroke color. All CSS3 colors are supported except for extended named colors.strokeOpacity
: The stroke opacity between 0.0 and 1.0.strokeWeight
: The stroke width in pixels.
Add Event Handlers
Features respond to events, such as mouseup
or mousedown
. You can add event
listeners to allow users to interact with the data on the map. In the below
example, we add a mouseover event, that displays information about the feature
under the mouse cursor.
// Set mouseover event for each feature. map.data.addListener('mouseover', function(event) { document.getElementById('info-box').textContent = event.feature.getProperty('letter'); });
Data layer events
The following events are common to all features, regardless of their geometry type:
addfeature
click
dblclick
mousedown
mouseout
mouseover
mouseup
removefeature
removeproperty
rightclick
setgeometry
setproperty
More information about these events can be found in the reference documentation for the google.maps.data class.
Change Appearance Dynamically
You can set the style of the Data layer by passing a function that computes the
style of each feature to the google.maps.data.setStyle()
method. This
function will be called each time a feature’s properties are updated.
In the below example, we add an event listener for the click
event that
updates the feature’s isColorful
property. The feature styling is updated to
reflect the change as soon as the property is set.
// Color each letter gray. Change the color when the isColorful property // is set to true. map.data.setStyle(function(feature) { var color = 'gray'; if (feature.getProperty('isColorful')) { color = feature.getProperty('color'); } return /** @type {!google.maps.Data.StyleOptions} */({ fillColor: color, strokeColor: color, strokeWeight: 2 }); }); // When the user clicks, set 'isColorful', changing the color of the letters. map.data.addListener('click', function(event) { event.feature.setProperty('isColorful', true); }); // When the user hovers, tempt them to click by outlining the letters. // Call revertStyle() to remove all overrides. This will use the style rules // defined in the function passed to setStyle() map.data.addListener('mouseover', function(event) { map.data.revertStyle(); map.data.overrideStyle(event.feature, {strokeWeight: 8}); }); map.data.addListener('mouseout', function(event) { map.data.revertStyle(); });