mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
gis: Fixed #7619. Added support Google Maps markers (GMarker
) and events (GEvent
). Thanks, Ludwig Brinckmann.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7841 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
ccd5f52ee7
commit
822a1259f6
@ -57,5 +57,5 @@
|
||||
version.
|
||||
"""
|
||||
from django.contrib.gis.maps.google.gmap import GoogleMap
|
||||
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline
|
||||
from django.contrib.gis.maps.google.overlays import GEvent, GMarker, GPolygon, GPolyline
|
||||
from django.contrib.gis.maps.google.zoom import GoogleZoom
|
||||
|
@ -4,7 +4,7 @@ from django.template.loader import render_to_string
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
class GoogleMapException(Exception): pass
|
||||
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline
|
||||
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker
|
||||
|
||||
# The default Google Maps URL (for the API javascript)
|
||||
# TODO: Internationalize for Japan, UK, etc.
|
||||
@ -20,7 +20,7 @@ class GoogleMap(object):
|
||||
|
||||
def __init__(self, key=None, api_url=None, version=None,
|
||||
center=None, zoom=None, dom_id='map', load_func='gmap_load',
|
||||
kml_urls=[], polygons=[], polylines=[],
|
||||
kml_urls=[], polygons=[], polylines=[], markers=[],
|
||||
template='gis/google/js/google-map.js',
|
||||
extra_context={}):
|
||||
|
||||
@ -55,8 +55,14 @@ class GoogleMap(object):
|
||||
self.template = template
|
||||
self.kml_urls = kml_urls
|
||||
|
||||
# Does the user want any GPolygon or GPolyline overlays?
|
||||
self.polygons, self.polylines = [], []
|
||||
# Does the user want any GMarker, GPolygon, and/or GPolyline overlays?
|
||||
self.polygons, self.polylines, self.markers = [], [], []
|
||||
if markers:
|
||||
for point in markers:
|
||||
if isinstance(point, GMarker):
|
||||
self.markers.append(point)
|
||||
else:
|
||||
self.markers.append(GMarker(point))
|
||||
if polygons:
|
||||
for poly in polygons:
|
||||
if isinstance(poly, GPolygon):
|
||||
@ -70,12 +76,13 @@ class GoogleMap(object):
|
||||
else:
|
||||
self.polylines.append(GPolyline(pline))
|
||||
|
||||
# If GPolygons and/or GPolylines are used the zoom will be automatically
|
||||
# If GMarker, GPolygons, and/or GPolylines
|
||||
# are used the zoom will be automatically
|
||||
# calculated via the Google Maps API. If both a zoom level and a
|
||||
# center coordinate are provided with polygons/polylines, no automatic
|
||||
# determination will occur.
|
||||
self.calc_zoom = False
|
||||
if self.polygons or self.polylines:
|
||||
if self.polygons or self.polylines or self.markers:
|
||||
if center is None or zoom is None:
|
||||
self.calc_zoom = True
|
||||
|
||||
@ -95,6 +102,7 @@ class GoogleMap(object):
|
||||
'zoom' : self.zoom,
|
||||
'polygons' : self.polygons,
|
||||
'polylines' : self.polylines,
|
||||
'markers' : self.markers,
|
||||
}
|
||||
params.update(extra_context)
|
||||
self.js = render_to_string(self.template, params)
|
||||
|
@ -1,10 +1,66 @@
|
||||
from django.contrib.gis.geos import LineString, LinearRing, Polygon
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.contrib.gis.geos import fromstr, Point, LineString, LinearRing, Polygon
|
||||
|
||||
class GEvent(object):
|
||||
"""
|
||||
A Python wrapper for the Google GEvent object.
|
||||
|
||||
Events can be attached to any object derived from GOverlayBase with the
|
||||
add_event() call.
|
||||
|
||||
For more information please see the Google Maps API Reference:
|
||||
http://code.google.com/apis/maps/documentation/reference.html#GEvent
|
||||
|
||||
Example:
|
||||
|
||||
from django.shortcuts import render_to_response
|
||||
from django.contrib.gis.maps.google import GoogleMap, GEvent, GPolyline
|
||||
|
||||
def sample_request(request):
|
||||
polyline = GPolyline('LINESTRING(101 26, 112 26, 102 31)')
|
||||
event = GEvent('click',
|
||||
'function() { location.href = "http://www.google.com"}')
|
||||
polyline.add_event(event)
|
||||
return render_to_response('mytemplate.html',
|
||||
{'google' : GoogleMap(polylines=[polyline])})
|
||||
"""
|
||||
|
||||
def __init__(self, event, action):
|
||||
"""
|
||||
Initializes a GEvent object.
|
||||
|
||||
Parameters:
|
||||
|
||||
event:
|
||||
string for the event, such as 'click'. The event must be a valid
|
||||
event for the object in the Google Maps API.
|
||||
There is no validation of the event type within Django.
|
||||
|
||||
action:
|
||||
string containing a Javascript function, such as
|
||||
'function() { location.href = "newurl";}'
|
||||
The string must be a valid Javascript function. Again there is no
|
||||
validation fo the function within Django.
|
||||
"""
|
||||
self.event = event
|
||||
self.action = action
|
||||
|
||||
def __unicode__(self):
|
||||
"Returns the parameter part of a GEvent."
|
||||
return mark_safe('"%s", %s' %(self.event, self.action))
|
||||
|
||||
class GOverlayBase(object):
|
||||
def __init__(self):
|
||||
self.events = []
|
||||
|
||||
def latlng_from_coords(self, coords):
|
||||
"Generates a JavaScript array of GLatLng objects for the given coordinates."
|
||||
return '[%s]' % ','.join(['new GLatLng(%s,%s)' % (y, x) for x, y in coords])
|
||||
|
||||
def add_event(self, event):
|
||||
"Attaches a GEvent to the overlay object."
|
||||
self.events.append(event)
|
||||
|
||||
def __unicode__(self):
|
||||
"The string representation is the JavaScript API call."
|
||||
return mark_safe('%s(%s)' % (self.__class__.__name__, self.js_params))
|
||||
@ -19,8 +75,9 @@ class GPolygon(GOverlayBase):
|
||||
stroke_color='#0000ff', stroke_weight=2, stroke_opacity=1,
|
||||
fill_color='#0000ff', fill_opacity=0.4):
|
||||
"""
|
||||
The GPolygon object initializes on a GEOS Polygon. Please note that
|
||||
this will not depict Polygons with internal rings.
|
||||
The GPolygon object initializes on a GEOS Polygon or a parameter that
|
||||
may be instantiated into GEOS Polygon. Please note that this will not
|
||||
depict a Polygon's internal rings.
|
||||
|
||||
Keyword Options:
|
||||
|
||||
@ -39,8 +96,8 @@ class GPolygon(GOverlayBase):
|
||||
fill_opacity:
|
||||
The opacity of the polygon fill. Defaults to 0.4.
|
||||
"""
|
||||
|
||||
# TODO: Take other types of geometries.
|
||||
if isinstance(poly, basestring): poly = fromstr(poly)
|
||||
if isinstance(poly, (tuple, list)): poly = Polygon(poly)
|
||||
if not isinstance(poly, Polygon):
|
||||
raise TypeError('GPolygon may only initialize on GEOS Polygons.')
|
||||
|
||||
@ -57,7 +114,9 @@ class GPolygon(GOverlayBase):
|
||||
|
||||
# Fill settings.
|
||||
self.fill_color, self.fill_opacity = fill_color, fill_opacity
|
||||
|
||||
|
||||
super(GPolygon, self).__init__()
|
||||
|
||||
@property
|
||||
def js_params(self):
|
||||
return '%s, "%s", %s, %s, "%s", %s' % (self.points, self.stroke_color, self.stroke_weight, self.stroke_opacity,
|
||||
@ -71,8 +130,9 @@ class GPolyline(GOverlayBase):
|
||||
"""
|
||||
def __init__(self, geom, color='#0000ff', weight=2, opacity=1):
|
||||
"""
|
||||
The GPolyline object may initialize on GEOS LineStirng, LinearRing,
|
||||
and Polygon objects (internal rings not supported).
|
||||
The GPolyline object may be initialized on GEOS LineStirng, LinearRing,
|
||||
and Polygon objects (internal rings not supported) or a parameter that
|
||||
may instantiated into one of the above geometries.
|
||||
|
||||
Keyword Options:
|
||||
|
||||
@ -85,6 +145,10 @@ class GPolyline(GOverlayBase):
|
||||
opacity:
|
||||
The opacity of the polyline, between 0 and 1. Defaults to 1.
|
||||
"""
|
||||
# If a GEOS geometry isn't passed in, try to contsruct one.
|
||||
if isinstance(geom, basestring): geom = fromstr(geom)
|
||||
if isinstance(geom, (tuple, list)): geom = Polygon(geom)
|
||||
# Generating the lat/lng coordinate pairs.
|
||||
if isinstance(geom, (LineString, LinearRing)):
|
||||
self.latlngs = self.latlng_from_coords(geom.coords)
|
||||
elif isinstance(geom, Polygon):
|
||||
@ -95,7 +159,62 @@ class GPolyline(GOverlayBase):
|
||||
# Getting the envelope for automatic zoom determination.
|
||||
self.envelope = geom.envelope
|
||||
self.color, self.weight, self.opacity = color, weight, opacity
|
||||
super(GPolyline, self).__init__()
|
||||
|
||||
@property
|
||||
def js_params(self):
|
||||
return '%s, "%s", %s, %s' % (self.latlngs, self.color, self.weight, self.opacity)
|
||||
|
||||
class GMarker(GOverlayBase):
|
||||
"""
|
||||
A Python wrapper for the Google GMarker object. For more information
|
||||
please see the Google Maps API Reference:
|
||||
http://code.google.com/apis/maps/documentation/reference.html#GMarker
|
||||
|
||||
Example:
|
||||
|
||||
from django.shortcuts import render_to_response
|
||||
from django.contrib.gis.maps.google.overlays import GMarker, GEvent
|
||||
|
||||
def sample_request(request):
|
||||
marker = GMarker('POINT(101 26)')
|
||||
event = GEvent('click',
|
||||
'function() { location.href = "http://www.google.com"}')
|
||||
marker.add_event(event)
|
||||
return render_to_response('mytemplate.html',
|
||||
{'google' : GoogleMap(markers=[marker])})
|
||||
"""
|
||||
def __init__(self, geom, title=None):
|
||||
"""
|
||||
The GMarker object may initialize on GEOS Points or a parameter
|
||||
that may be instantiated into a GEOS point. Keyword options map to
|
||||
GMarkerOptions -- so far only the title option is supported.
|
||||
|
||||
Keyword Options:
|
||||
title:
|
||||
Title option for GMarker, will be displayed as a tooltip.
|
||||
"""
|
||||
# If a GEOS geometry isn't passed in, try to construct one.
|
||||
if isinstance(geom, basestring): geom = fromstr(geom)
|
||||
if isinstance(geom, (tuple, list)): geom = Point(geom)
|
||||
if isinstance(geom, Point):
|
||||
self.latlng = self.latlng_from_coords(geom.coords)
|
||||
else:
|
||||
raise TypeError('GMarker may only initialize on GEOS Point geometry.')
|
||||
# Getting the envelope for automatic zoom determination.
|
||||
self.envelope = geom.envelope
|
||||
# TODO: Add support for more GMarkerOptions
|
||||
self.title = title
|
||||
super(GMarker, self).__init__()
|
||||
|
||||
def latlng_from_coords(self, coords):
|
||||
return 'new GLatLng(%s,%s)' %(coords[1], coords[0])
|
||||
|
||||
def options(self):
|
||||
result = []
|
||||
if self.title: result.append('title: "%s"' % self.title)
|
||||
return '{%s}' % ','.join(result)
|
||||
|
||||
@property
|
||||
def js_params(self):
|
||||
return '%s, %s' % (self.latlng, self.options())
|
||||
|
@ -3,17 +3,28 @@
|
||||
{% block load %}function {{ load_func }}(){
|
||||
if (GBrowserIsCompatible()) {
|
||||
map = new GMap2(document.getElementById("{{ dom_id }}"));
|
||||
map.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});
|
||||
{% block controls %}map.addControl(new GSmallMapControl());
|
||||
map.addControl(new GMapTypeControl());{% endblock %}
|
||||
{% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% else %}map.setCenter(new GLatLng({{ center.1 }}, {{ center.0 }}), {{ zoom }});{% endif %}
|
||||
{% if calc_zoom %}var bounds = new GLatLngBounds(); var tmp_bounds = new GLatLngBounds();{% endif %}
|
||||
{% for kml_url in kml_urls %}var kml{{ forloop.counter }} = new GGeoXml("{{ kml_url }}");
|
||||
map.addOverlay(kml{{ forloop.counter }});{% endfor %}
|
||||
|
||||
{% for polygon in polygons %}var poly{{ forloop.counter }} = new {{ polygon }};
|
||||
map.addOverlay(poly{{ forloop.counter }});{% if calc_zoom %}
|
||||
tmp_bounds = poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||
map.addOverlay(poly{{ forloop.counter }});
|
||||
{% for event in polygon.events %}GEvent.addListener(poly{{ forloop.parentloop.counter }}, {{ event }});{% endfor %}
|
||||
{% if calc_zoom %}tmp_bounds = poly{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||
|
||||
{% for polyline in polylines %}var polyline{{ forloop.counter }} = new {{ polyline }};
|
||||
map.addOverlay(polyline{{ forloop.counter }});{% if calc_zoom %}
|
||||
tmp_bounds = polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||
map.addOverlay(polyline{{ forloop.counter }});
|
||||
{% for event in polyline.events %}GEvent.addListener(polyline{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
||||
{% if calc_zoom %}tmp_bounds = polyline{{ forloop.counter }}.getBounds(); bounds.extend(tmp_bounds.getSouthWest()); bounds.extend(tmp_bounds.getNorthEast());{% endif %}{% endfor %}
|
||||
|
||||
{% for marker in markers %}var marker{{ forloop.counter }} = new {{ marker }};
|
||||
map.addOverlay(marker{{ forloop.counter }});
|
||||
{% for event in marker.events %}GEvent.addListener(marker{{ forloop.parentloop.counter }}, {{ event }}); {% endfor %}
|
||||
{% if calc_zoom %}bounds.extend(marker{{ forloop.counter }}.getLatLng()); {% endif %}{% endfor %}
|
||||
|
||||
{% if calc_zoom %}map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));{% endif %}
|
||||
{% block load_extra %}{% endblock %}
|
||||
}else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user