Drawing geojson-based polygons on Google Maps
This post will demonstrate how to draw polygons on Google Maps v3 using geojson-encoded data from GeoDjango. The most common method for displaying polygons on Google Maps seems to be by using KML. Google Maps requires the KML-file to be available on a public website though and that is kind of a bore for debugging. This approach uses only json and the standard maps drawing API. To get the display the polygons, you have to loop over them and do a setMap()
with your map.
I’m assuming the browser is getting geojson from from a GeoDjango model object like this: model.area.geojson
, but it should work for data from other sources. Note that I’m using the very excellent Underscore.js Javascript library to do really terse functional programming. Also note that the function takes an optional bounds
object which gets expanded as polygon points are added.
The code seems to perform very well in modern browsers, even for fairly large and complex polygons. Unfortunately there is no live demo, but the site I’m working on should go up soon.
function createPolygons(areajson, bounds){ var coords = areajson.coordinates; var polygons = _(coords).reduce([], function(memo_n, n) { var polygonpaths = _(n).reduce(new google.maps.MVCArray(), function(memo_o, o) { var polygoncords = _(o).reduce(new google.maps.MVCArray(), function(memo_p, p) { var mylatlng = new google.maps.LatLng(p[1], p[0]); if(bounds){ bounds.extend(mylatlng); } memo_p.push(mylatlng); return memo_p; }); memo_o.push(polygoncords); return memo_o; }); var polygon = new google.maps.Polygon({ paths: polygonpaths, strokeColor: "#808080", strokeOpacity: 0.8, strokeWeight: 2, fillColor: "#C0C0C0", fillOpacity: 0.35 }); memo_n.push(polygon); return memo_n; }); return polygons; }
9 thoughts on “Drawing geojson-based polygons on Google Maps”-
-
-
-
-
-
-
-
-
Jason says:
Do you know if this method works with “Polygon” and “MultiPolygon” formatted JSON? I was looking for some help creating polygons from “MultiPolygon” formatted JSON using jQuery and found this site. I might have to give underscore a look!
friism says:
I use this code for rendering Multipolygons, and it works great, both for areas consisting of several disjoint polygons and for areas with “holes” in them.
Jason says:
I should have updated my comment earlier. I’m using your code and it works beautifully. Now if I can only understand why…off to study some _.
Haes says:
Thanks for this blog entry. Would you care to post a complete example, including a view and the rest of the javascript in the template?
I’m having some difficulties to get this running and I’m not quite sure what’s the problem.
Steve says:
Where in this are you passing in your geojson? I guess that you wanted it like…
var coords = {{mymodel.geom.geojson}}
but that obv doesn’t work. Also, where are you initializing the map? I don’t need the view but the template sure would help me 😀
friism says:
@Steve: I’m passing in the geojson in the ‘areajson’ parameter. And I output it the way you mention, although I pass through the |safe filter. Why is this not working for you?
The map init code is not in the snippet above, but it is not directly relevant. Just remember that when you have both map and polygons going, you need to call setMap(map) on each polygon.
Steve says:
Here is the complete view as I have it, where zipcode is a multipolygon with four paths:
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
#map_canvas { height: 100% }
function initialize() {
var latlng = new google.maps.LatLng({{ zipcode.geom.centroid.y}},
{{ zipcode.geom.centroid.x}});
var myOptions = {
zoom: {{ zoom }},
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById(“map_canvas”),
myOptions);
function createPolygons(areajson, bounds){
var coords = {{zipcode.geom.geojson|safe}};
var polygons = _(coords).reduce([], function(memo_n, n) {
var polygonpaths = _(n).reduce(new google.maps.MVCArray(), function(memo_o, o) {
var polygoncords = _(o).reduce(new google.maps.MVCArray(), function(memo_p, p) {
var mylatlng = new google.maps.LatLng(p[1], p[0]);
if(bounds){
bounds.extend(mylatlng);
}
memo_p.push(mylatlng);
return memo_p;
});
memo_o.push(polygoncords);
return memo_o;
});
var polygon = new google.maps.Polygon({
paths: polygonpaths,
strokeColor: “#808080”,
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: “#C0C0C0”,
fillOpacity: 0.35
});
memo_n.push(polygon);
return memo_n;
});
return polygons;
};
polygon.setMap(map);
};
Kevin says:
Hi Michel, not sure if you’re still monitoring this post, but when I try to run it I get an error from underscore.js saying ‘Uncaught TypeError: is not a function’ – has something changed in underscore since you wrote your code? Thanks for any insight you can provide!
admin says:
@Kevin, I haven’t looked at this recently, you may have to debug it yourself.
Michael