Mapping better – Google Maps API v3

I tend to do my Google v3 work purely in my templates.

For this example I’ve got a view that will return the objects to be displayed in `object_list` in the context – same dataset as last time, only instead of building things inside the view we’ll do it in our Django template.

from uscampgrounds.models import Campground

def gmap3(request):
    campgrounds = Campground.objects.filter(point__distance_lte=(Point((-94, 37)), D(mi=100)))

    return render_to_response('gmap3.html', {
        'object_list': campgrounds,
    }, context_instance=RequestContext(request))

For our base template – defining a map area, loading the initial Google JavaScript: (I named it gmap3base.html because there are several base and normal templates in the project I’m building from)

<html>
    <head>
        <title>{% block page-title %}Simple Google Maps API v3{% endblock %}</title>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
        {% block head_override %}{% endblock head_override %}
    </head>
    <body{% block body_override %}{% endblock body_override %}>
        {% block content %}
        {% endblock content %}
    </body>
</html>

Next our map creating template (I named mine gmap3.html):

{% extends "gmap3base.html" %}

{% block page-title %}Requested Items{% endblock %}

{% block head_override %}
<script type="text/javascript">
  var bounds = new google.maps.LatLngBounds();

  function buildMarker(map, latitude, longitude, name, color) {
    var latlng = new google.maps.LatLng(latitude, longitude);
    var marker = new google.maps.Marker({
          position: latlng,
          map: map,
          title:name,
    });
    marker.setIcon('http://maps.google.com/mapfiles/ms/icons/' + color + '-dot.png');
    bounds.extend(latlng);
    return marker
  }

  function mapInitialize() {
    var myOptions = {
      zoom: 6,
      center: new google.maps.LatLng(0, 0),
      mapTypeId: google.maps.MapTypeId.SATELLITE
    };
    var map = new google.maps.Map(document.getElementById("map_canvas"),
        myOptions);

    {% for object in object_list %}marker{{ object.pk }} = buildMarker(map, {{ object.point.y }}, {{ object.point.x }}, "{{ object }}", 'red');
    {% endfor %}

    map.fitBounds(bounds);
  }

</script>
{% endblock head_override %}

{% block body_override %} onload="mapInitialize()"{% endblock body_override %}

{% block content %}
<div id="map_canvas" style='width:600px;height:400px;'></div>
{% endblock content %}

This doesn’t do anything fancy – just the simple behavior we got from using GeoDjango’s map generator – but since we generated the JavaScript ourselves, we know what things will be named and can add on our own JavaScript much easier – and this works without modification. No API key creating, switching based on what site we’re on, it just works.

Since we generated normal JavaScript we also have the benefit of being able to use tutorials and examples found all over the internet to fine tune things. Want an onClick event that opens an infoWindow? It’s quite easy. Want to do zooming differently, say to a range from the search point instead of making every point visible? You can do that too. [you will need another geometry passed into the context for the search location in order to do this]

Leave a Reply

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