@@ -55,6 +55,8 @@ def __init__(
5555 layer = "" ,
5656 map_ids = None ,
5757 bicycle_layer = False ,
58+ heatmap_data = None ,
59+ heatmap_layer = False ,
5860 ** kwargs
5961 ):
6062 # type: (...) -> None
@@ -68,7 +70,7 @@ def __init__(
6870 self .zoom = zoom
6971 self .maptype = maptype
7072 self .markers = [] # type: List[Any]
71- self .map_ids = map_ids ,
73+ self .map_ids = map_ids
7274 self .build_markers (markers )
7375 self .rectangles = [] # type: List[Any]
7476 self .build_rectangles (rectangles )
@@ -102,6 +104,9 @@ def __init__(
102104 self .styles = styles
103105 self .layer = layer
104106 self .bicycle_layer = bicycle_layer
107+ self .heatmap_layer = heatmap_layer
108+ self .heatmap_data = []
109+ self .build_heatmap (heatmap_data , heatmap_layer )
105110
106111 def build_markers (self , markers ):
107112 # type: (Optional[Union[Dict, List, Tuple]]) -> None
@@ -149,7 +154,7 @@ def add_marker(self, lat=None, lng=None, **kwargs):
149154
150155 def build_rectangles (self , rectangles ):
151156 # type: (Optional[List[Union[List, Tuple, Tuple[Tuple], Dict]]]) -> None
152- """ Process data to construct rectangles
157+ """Process data to construct rectangles
153158
154159 This method is built from the assumption that the rectangles parameter
155160 is a list of:
@@ -227,7 +232,7 @@ def build_rectangle_dict(
227232 fill_opacity = 0.3 , # type: float
228233 ):
229234 # type: (...) -> Dict
230- """ Set a dictionary with the javascript class Rectangle parameters
235+ """Set a dictionary with the javascript class Rectangle parameters
231236
232237 This function sets a default drawing configuration if the user just
233238 pass the rectangle bounds, but also allows to set each parameter
@@ -260,7 +265,7 @@ def build_rectangle_dict(
260265
261266 def add_rectangle (self , north = None , west = None , south = None , east = None , ** kwargs ):
262267 # type: (Optional[float], Optional[float], Optional[float], Optional[float], **Any) -> None
263- """ Adds a rectangle dict to the Map.rectangles attribute
268+ """Adds a rectangle dict to the Map.rectangles attribute
264269
265270 The Google Maps API describes a rectangle using the LatLngBounds
266271 object, which defines the bounds to be drawn. The bounds use the
@@ -307,7 +312,7 @@ def add_rectangle(self, north=None, west=None, south=None, east=None, **kwargs):
307312
308313 def build_circles (self , circles ):
309314 # type: (Optional[List[Union[List, Tuple, Dict]]]) -> None
310- """ Process data to construct rectangles
315+ """Process data to construct rectangles
311316
312317 This method is built from the assumption that the circles parameter
313318 is a list of:
@@ -359,7 +364,7 @@ def build_circle_dict(
359364 clickable = True , # type: bool
360365 ):
361366 # type: (...) -> Dict
362- """ Set a dictionary with the javascript class Circle parameters
367+ """Set a dictionary with the javascript class Circle parameters
363368
364369 This function sets a default drawing configuration if the user just
365370 pass the rectangle bounds, but also allows to set each parameter
@@ -394,7 +399,7 @@ def build_circle_dict(
394399
395400 def add_circle (self , center_lat = None , center_lng = None , radius = None , ** kwargs ):
396401 # type: (Optional[float], Optional[float], Optional[float], **Any) -> None
397- """ Adds a circle dict to the Map.circles attribute
402+ """Adds a circle dict to the Map.circles attribute
398403
399404 The circle in a sphere is called "spherical cap" and is defined in the
400405 Google Maps API by at least the center coordinates and its radius, in
@@ -436,7 +441,7 @@ def add_circle(self, center_lat=None, center_lng=None, radius=None, **kwargs):
436441
437442 def build_polylines (self , polylines ):
438443 # type: (Optional[List[Union[List, Tuple, Dict]]]) -> None
439- """ Process data to construct polylines
444+ """Process data to construct polylines
440445
441446 This method is built from the assumption that the polylines parameter
442447 is a list of:
@@ -500,7 +505,7 @@ def build_polyline_dict(
500505 self , path , stroke_color = "#FF0000" , stroke_opacity = 0.8 , stroke_weight = 2
501506 ):
502507 # type: (List[Dict], str, float, int) -> Dict
503- """ Set a dictionary with the javascript class Polyline parameters
508+ """Set a dictionary with the javascript class Polyline parameters
504509
505510 This function sets a default drawing configuration if the user just
506511 pass the polyline path, but also allows to set each parameter
@@ -532,7 +537,7 @@ def build_polyline_dict(
532537
533538 def add_polyline (self , path = None , ** kwargs ):
534539 # type: (Optional[List[Dict]], **Any) -> None
535- """ Adds a polyline dict to the Map.polylines attribute
540+ """Adds a polyline dict to the Map.polylines attribute
536541
537542 The Google Maps API describes a polyline as a "linear overlay of
538543 connected line segments on the map". The linear paths are defined
@@ -577,7 +582,7 @@ def add_polyline(self, path=None, **kwargs):
577582
578583 def build_polygons (self , polygons ):
579584 # type: (Optional[List[Union[List, Tuple, Dict]]]) -> None
580- """ Process data to construct polygons
585+ """Process data to construct polygons
581586
582587 This method is built from the assumption that the polygons parameter
583588 is a list of:
@@ -649,7 +654,7 @@ def build_polygon_dict(
649654 fill_opacity = 0.3 , # type: float
650655 ):
651656 # type: (...) -> Dict
652- """ Set a dictionary with the javascript class Polygon parameters
657+ """Set a dictionary with the javascript class Polygon parameters
653658
654659 This function sets a default drawing configuration if the user just
655660 pass the polygon path, but also allows to set each parameter
@@ -687,7 +692,7 @@ def build_polygon_dict(
687692
688693 def add_polygon (self , path = None , ** kwargs ):
689694 # type: (Optional[List[Dict]], **Any) -> None
690- """ Adds a polygon dict to the Map.polygons attribute
695+ """Adds a polygon dict to the Map.polygons attribute
691696
692697 The Google Maps API describes a polyline as a "linear overlay of
693698 connected line segments on the map" and "form a closed loop and define
@@ -733,6 +738,37 @@ def add_polygon(self, path=None, **kwargs):
733738
734739 self .polygons .append (kwargs )
735740
741+ def build_heatmap (self , heatmap_data , heatmap_layer ):
742+ # type: (list, bool) -> dict
743+ if not heatmap_layer :
744+ return
745+ if heatmap_layer and not heatmap_data :
746+ raise AttributeError ("heatmap_later requires 'heatmap_data'" )
747+ if not isinstance (heatmap_data , (list )):
748+ raise AttributeError (
749+ "heatmap_data only accepts a list of dicts with keys 'lat' 'lng' and their corresponding values"
750+ )
751+ for hm in heatmap_data :
752+ if isinstance (hm , dict ):
753+ self .add_heatmap (** hm )
754+ else :
755+ raise AttributeError (
756+ "elements of list 'heatmap_data' must be a dict of keys 'lat' and 'lng' with their corresponding values"
757+ )
758+
759+ def add_heatmap (self , lat = None , lng = None , ** kwargs ):
760+ # type: (Optional[float], Optional[float], **Any) -> None
761+ if lat is not None :
762+ kwargs ["lat" ] = lat
763+ if lng is not None :
764+ kwargs ["lng" ] = lng
765+ if "lat" not in kwargs or "lng" not in kwargs :
766+ raise AttributeError ("heatmap_data requires 'lat' and 'lng' values" )
767+ if len (kwargs ) > 2 :
768+ raise AttributeError ("heatmap_data can only contain 'lat' and 'lng' values" )
769+
770+ self .heatmap_data .append (kwargs )
771+
736772 def render (self , * args , ** kwargs ):
737773 # type: (*Any, **Any) -> Text
738774 return render_template (* args , ** kwargs )
@@ -773,10 +809,12 @@ def as_json(self):
773809 def verify_lat_lng_coordinates (self , lat , lng ):
774810 if not (90 >= lat >= - 90 ):
775811 raise AttributeError (
776- "Latitude must be between -90 and 90 degrees inclusive." )
812+ "Latitude must be between -90 and 90 degrees inclusive."
813+ )
777814 if not (180 >= lng >= - 180 ):
778815 raise AttributeError (
779- "Longitude must be between -180 and 180 degrees inclusive." )
816+ "Longitude must be between -180 and 180 degrees inclusive."
817+ )
780818
781819 return (lat , lng )
782820
0 commit comments