Drawing geojson-based polygons on Google Maps

Posted on |

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”

  • 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!

  • 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.

  • 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 _.

  • 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.

  • 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 😀

  • @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.

  • 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);
    };

  • 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!


Warning: Undefined variable $aria_req in /var/www/html/wp-content/themes/friism/comments.php on line 95

Warning: Undefined variable $aria_req in /var/www/html/wp-content/themes/friism/comments.php on line 96

Warning: Undefined variable $aria_req in /var/www/html/wp-content/themes/friism/comments.php on line 97

Leave a Reply to Haes Cancel Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>