Fixed #9204 -- Added `GIcon` overlay, allowing customization for icons of `GMarker` objects. Thanks to qingfeng for initial ticket/patch, and to prairiedogg for final implementation.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10021 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2009-03-10 18:03:35 +00:00
parent 326c5813b9
commit 6aa5aacc86
4 changed files with 132 additions and 55 deletions

View File

@ -57,5 +57,5 @@
version. version.
""" """
from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet from django.contrib.gis.maps.google.gmap import GoogleMap, GoogleMapSet
from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, GPolyline from django.contrib.gis.maps.google.overlays import GEvent, GIcon, GMarker, GPolygon, GPolyline
from django.contrib.gis.maps.google.zoom import GoogleZoom from django.contrib.gis.maps.google.zoom import GoogleZoom

View File

@ -4,7 +4,7 @@ from django.template.loader import render_to_string
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
class GoogleMapException(Exception): pass class GoogleMapException(Exception): pass
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker, GIcon
# The default Google Maps URL (for the API javascript) # The default Google Maps URL (for the API javascript)
# TODO: Internationalize for Japan, UK, etc. # TODO: Internationalize for Japan, UK, etc.
@ -20,9 +20,10 @@ class GoogleMap(object):
def __init__(self, key=None, api_url=None, version=None, def __init__(self, key=None, api_url=None, version=None,
center=None, zoom=None, dom_id='map', center=None, zoom=None, dom_id='map',
kml_urls=[], polygons=[], polylines=[], markers=[], kml_urls=[], polylines=None, polygons=None, markers=None,
template='gis/google/google-single.js', template='gis/google/google-single.js',
js_module='geodjango',extra_context={}): js_module='geodjango',
extra_context={}):
# The Google Maps API Key defined in the settings will be used # The Google Maps API Key defined in the settings will be used
# if not passed in as a parameter. The use of an API key is # if not passed in as a parameter. The use of an API key is
@ -57,25 +58,21 @@ class GoogleMap(object):
self.kml_urls = kml_urls self.kml_urls = kml_urls
# Does the user want any GMarker, GPolygon, and/or GPolyline overlays? # Does the user want any GMarker, GPolygon, and/or GPolyline overlays?
self.polygons, self.polylines, self.markers = [], [], [] overlay_info = [[GMarker, markers, 'markers'],
if markers: [GPolygon, polygons, 'polygons'],
for point in markers: [GPolyline, polylines, 'polylines']]
if isinstance(point, GMarker):
self.markers.append(point) for overlay_class, overlay_list, varname in overlay_info:
else: setattr(self, varname, [])
self.markers.append(GMarker(point)) if overlay_list:
if polygons: for overlay in overlay_list:
for poly in polygons: if isinstance(overlay, overlay_class):
if isinstance(poly, GPolygon): getattr(self, varname).append(overlay)
self.polygons.append(poly) else:
else: getattr(self, varname).append(overlay_class(overlay))
self.polygons.append(GPolygon(poly))
if polylines: # Pulling any icons from the markers.
for pline in polylines: self.icons = [marker.icon for marker in self.markers if marker.icon]
if isinstance(pline, GPolyline):
self.polylines.append(pline)
else:
self.polylines.append(GPolyline(pline))
# If GMarker, GPolygons, and/or GPolylines are used the zoom will be # If GMarker, GPolygons, and/or GPolylines are used the zoom will be
# automatically calculated via the Google Maps API. If both a zoom # automatically calculated via the Google Maps API. If both a zoom
@ -105,6 +102,7 @@ class GoogleMap(object):
'zoom' : self.zoom, 'zoom' : self.zoom,
'polygons' : self.polygons, 'polygons' : self.polygons,
'polylines' : self.polylines, 'polylines' : self.polylines,
'icons': self.icons,
'markers' : self.markers, 'markers' : self.markers,
} }
params.update(self.extra_context) params.update(self.extra_context)
@ -175,6 +173,11 @@ class GoogleMapSet(GoogleMap):
else: else:
self.maps = args self.maps = args
# Creating the icons sequence from every map in this set.
self.icons = []
for map in self.maps:
self.icons.extend(map.icons)
# Generating DOM ids for each of the maps in the set. # Generating DOM ids for each of the maps in the set.
self.dom_ids = ['map%d' % i for i in xrange(len(self.maps))] self.dom_ids = ['map%d' % i for i in xrange(len(self.maps))]
@ -205,6 +208,7 @@ class GoogleMapSet(GoogleMap):
params = {'js_module' : self.js_module, params = {'js_module' : self.js_module,
'dom_ids' : self.dom_ids, 'dom_ids' : self.dom_ids,
'load_map_js' : self.load_map_js(), 'load_map_js' : self.load_map_js(),
'icons' : self.icons,
} }
params.update(self.extra_context) params.update(self.extra_context)
return render_to_string(self.template, params) return render_to_string(self.template, params)

View File

@ -165,6 +165,72 @@ class GPolyline(GOverlayBase):
def js_params(self): def js_params(self):
return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity) return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity)
class GIcon(object):
"""
Creates a GIcon object to pass into a Gmarker object.
The keyword arguments map to instance attributes of the same name. These,
in turn, correspond to a subset of the attributes of the official GIcon
javascript object:
http://code.google.com/apis/maps/documentation/reference.html#GIcon
Because a Google map often uses several different icons, a name field has
been added to the required arguments.
Required Arguments:
varname:
A string which will become the basis for the js variable name of
the marker, for this reason, your code should assign a unique
name for each GIcon you instantiate, otherwise there will be
name space collisions in your javascript.
Keyword Options:
image:
The url of the image to be used as the icon on the map defaults
to 'G_DEFAULT_ICON'
iconsize:
a tuple representing the pixel size of the foreground (not the
shadow) image of the icon, in the format: (width, height) ex.:
GIcon('fast_food',
image="/media/icon/star.png",
iconsize=(15,10))
Would indicate your custom icon was 15px wide and 10px height.
shadow:
the url of the image of the icon's shadow
shadowsize:
a tuple representing the pixel size of the shadow image, format is
the same as ``iconsize``
iconanchor:
a tuple representing the pixel coordinate relative to the top left
corner of the icon image at which this icon is anchored to the map.
In (x, y) format. x increases to the right in the Google Maps
coordinate system and y increases downwards in the Google Maps
coordinate system.)
infowindowanchor:
The pixel coordinate relative to the top left corner of the icon
image at which the info window is anchored to this icon.
"""
def __init__(self, varname, image=None, iconsize=None,
shadow=None, shadowsize=None, iconanchor=None,
infowindowanchor=None):
self.varname = varname
self.image = image
self.iconsize = iconsize
self.shadow = shadow
self.shadowsize = shadowsize
self.iconanchor = iconanchor
self.infowindowanchor = infowindowanchor
class GMarker(GOverlayBase): class GMarker(GOverlayBase):
""" """
A Python wrapper for the Google GMarker object. For more information A Python wrapper for the Google GMarker object. For more information
@ -184,7 +250,7 @@ class GMarker(GOverlayBase):
return render_to_response('mytemplate.html', return render_to_response('mytemplate.html',
{'google' : GoogleMap(markers=[marker])}) {'google' : GoogleMap(markers=[marker])})
""" """
def __init__(self, geom, title=None, draggable=False): def __init__(self, geom, title=None, draggable=False, icon=None):
""" """
The GMarker object may initialize on GEOS Points or a parameter The GMarker object may initialize on GEOS Points or a parameter
that may be instantiated into a GEOS point. Keyword options map to that may be instantiated into a GEOS point. Keyword options map to
@ -209,6 +275,7 @@ class GMarker(GOverlayBase):
# TODO: Add support for more GMarkerOptions # TODO: Add support for more GMarkerOptions
self.title = title self.title = title
self.draggable = draggable self.draggable = draggable
self.icon = icon
super(GMarker, self).__init__() super(GMarker, self).__init__()
def latlng_from_coords(self, coords): def latlng_from_coords(self, coords):
@ -217,6 +284,7 @@ class GMarker(GOverlayBase):
def options(self): def options(self):
result = [] result = []
if self.title: result.append('title: "%s"' % self.title) if self.title: result.append('title: "%s"' % self.title)
if self.icon: result.append('icon: %s' % self.icon.varname)
if self.draggable: result.append('draggable: true') if self.draggable: result.append('draggable: true')
return '{%s}' % ','.join(result) return '{%s}' % ','.join(result)

View File

@ -1,2 +1,7 @@
{% block vars %}var geodjango = {};{% endblock %} {% block vars %}var geodjango = {};{% for icon in icons %}
var {{ icon.varname }} = new GIcon(G_DEFAULT_ICON);
{% if icon.image %}{{ icon.varname }}.image = "{{ icon.image }}";{% endif %}
{% if icon.shadow %}{{ icon.varname }}.shadow = "{{ icon.shadow }}";{% endif %} {% if icon.shadowsize %}{{ icon.varname }}.shadowSize = new GSize({{ icon.shadowsize.0 }}, {{ icon.shadowsize.1 }});{% endif %}
{% if icon.iconanchor %}{{ icon.varname }}.iconAnchor = new GPoint({{ icon.iconanchor.0 }}, {{ icon.iconanchor.1 }});{% endif %} {% if icon.iconsize %}{{ icon.varname }}.iconSize = new GSize({{ icon.iconsize.0 }}, {{ icon.iconsize.1 }});{% endif %}
{% if icon.infowindowanchor %}{{ icon.varname }}.infoWindowAnchor = new GPoint({{ icon.infowindowanchor.0 }}, {{ icon.infowindowanchor.1 }});{% endif %}{% endfor %}{% endblock %}
{% block functions %}{% endblock %} {% block functions %}{% endblock %}