Skip to content

Commit a1cdff8

Browse files
authored
Merge pull request #723 from ocefpaf/refact_rect_pol
Refactor Rectangle and Polygon
2 parents 5fc7fef + 3c2e696 commit a1cdff8

12 files changed

+749
-625
lines changed

CHANGES.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
0.6.0
2+
~~~~~
3+
4+
- Added `tooltip` support to all vector layers (ocefpaf #721)
5+
6+
API changes
7+
8+
- `Rectangle` and `Polygon` were renamed and set to leaflet's defaults.
9+
Both now accepted all `Path`'s optional arguments (ocefpaf #721)
10+
11+
Bug Fixes
12+
13+
- Unify `get_bounds` routine to avoid wrong responses
14+
- If Path option `fill_color` is present it will override `fill=False`
15+
116
0.5.0
217
~~~~~
318

examples/Features.ipynb

Lines changed: 46 additions & 36 deletions
Large diffs are not rendered by default.

examples/RectangleMarker_and_PolygonMarker.ipynb

Lines changed: 0 additions & 201 deletions
This file was deleted.

examples/Rectangle_and_Polygon.ipynb

Lines changed: 231 additions & 0 deletions
Large diffs are not rendered by default.

folium/features.py

Lines changed: 106 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ class PolyLine(Marker):
4444
See http://leafletjs.com/reference-1.2.0.html#polyline for more options.
4545
4646
"""
47-
def __init__(self, locations, popup=None, **kw):
47+
def __init__(self, locations, popup=None, tooltip=None, **kw):
4848
super(PolyLine, self).__init__(location=locations, popup=popup)
4949
self._name = 'PolyLine'
50+
self.tooltip = tooltip
5051
options = _parse_path(**kw)
5152
options.update(
5253
{
@@ -61,30 +62,13 @@ def __init__(self, locations, popup=None, **kw):
6162
{% macro script(this, kwargs) %}
6263
var {{this.get_name()}} = L.polyline(
6364
{{this.location}},
64-
{{ this.options }}).addTo({{this._parent.get_name()}});
65+
{{ this.options }}
66+
)
67+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
68+
.addTo({{this._parent.get_name()}});
6569
{% endmacro %}
6670
""") # noqa
6771

68-
def _get_self_bounds(self):
69-
"""
70-
Computes the bounds of the object itself (not including it's children)
71-
in the form [[lat_min, lon_min], [lat_max, lon_max]]
72-
73-
"""
74-
bounds = [[None, None], [None, None]]
75-
for point in iter_points(self.location):
76-
bounds = [
77-
[
78-
none_min(bounds[0][0], point[0]),
79-
none_min(bounds[0][1], point[1]),
80-
],
81-
[
82-
none_max(bounds[1][0], point[0]),
83-
none_max(bounds[1][1], point[1]),
84-
],
85-
]
86-
return bounds
87-
8872

8973
class WmsTileLayer(Layer):
9074
"""
@@ -464,10 +448,11 @@ class GeoJson(Layer):
464448
"""
465449
def __init__(self, data, style_function=None, name=None,
466450
overlay=True, control=True, smooth_factor=None,
467-
highlight_function=None):
451+
highlight_function=None, tooltip=None):
468452
super(GeoJson, self).__init__(name=name, overlay=overlay,
469453
control=control)
470454
self._name = 'GeoJson'
455+
self.tooltip = tooltip
471456
if isinstance(data, dict):
472457
self.embed = True
473458
self.data = data
@@ -542,7 +527,9 @@ def highlight_function(x):
542527
{% endif %}
543528
}
544529
{% endif %}
545-
).addTo({{this._parent.get_name()}});
530+
)
531+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
532+
.addTo({{this._parent.get_name()}});
546533
{{this.get_name()}}.setStyle(function(feature) {return feature.properties.style;});
547534
548535
{% endmacro %}
@@ -566,7 +553,7 @@ def style_data(self):
566553
feature.setdefault('properties', {}).setdefault('highlight', {}).update(self.highlight_function(feature)) # noqa
567554
return json.dumps(self.data, sort_keys=True)
568555

569-
def _get_self_bounds(self):
556+
def get_bounds(self):
570557
"""
571558
Computes the bounds of the object itself (not including it's children)
572559
in the form [[lat_min, lon_min], [lat_max, lon_max]]
@@ -646,10 +633,12 @@ class TopoJson(Layer):
646633
647634
"""
648635
def __init__(self, data, object_path, style_function=None,
649-
name=None, overlay=True, control=True, smooth_factor=None):
636+
name=None, overlay=True, control=True, smooth_factor=None,
637+
tooltip=None):
650638
super(TopoJson, self).__init__(name=name, overlay=overlay,
651639
control=control)
652640
self._name = 'TopoJson'
641+
self.tooltip = tooltip
653642
if 'read' in dir(data):
654643
self.embed = True
655644
self.data = json.load(data)
@@ -677,7 +666,10 @@ def style_function(x):
677666
{{this.get_name()}}_data.{{this.object_path}})
678667
{% if this.smooth_factor is not none %}
679668
, {smoothFactor: {{this.smooth_factor}}}
680-
{% endif %}).addTo({{this._parent.get_name()}});
669+
{% endif %}
670+
)
671+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
672+
.addTo({{this._parent.get_name()}});
681673
{{this.get_name()}}.setStyle(function(feature) {return feature.properties.style;});
682674
683675
{% endmacro %}
@@ -711,7 +703,7 @@ def render(self, **kwargs):
711703
JavascriptLink('https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js'), # noqa
712704
name='topojson')
713705

714-
def _get_self_bounds(self):
706+
def get_bounds(self):
715707
"""
716708
Computes the bounds of the object itself (not including it's children)
717709
in the form [[lat_min, lon_min], [lat_max, lon_max]]
@@ -822,21 +814,24 @@ class Circle(Marker):
822814
See http://leafletjs.com/reference-1.2.0.html#path for more otions.
823815
824816
"""
825-
def __init__(self, location, radius=10, popup=None, **kwargs):
817+
def __init__(self, location, radius=10, popup=None, tooltip=None, **kwargs):
826818
super(Circle, self).__init__(location=location, popup=popup)
827819
self._name = 'circle'
828-
options = _parse_path(**kwargs)
820+
self.tooltip = tooltip
829821

822+
options = _parse_path(**kwargs)
830823
options.update({'radius': radius})
831824
self.options = json.dumps(options, sort_keys=True, indent=2)
832825

833826
self._template = Template(u"""
834827
{% macro script(this, kwargs) %}
835828
836829
var {{this.get_name()}} = L.circle(
837-
[{{this.location[0]}},{{this.location[1]}}],
830+
[{{this.location[0]}}, {{this.location[1]}}],
838831
{{ this.options }}
839-
).addTo({{this._parent.get_name()}});
832+
)
833+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
834+
.addTo({{this._parent.get_name()}});
840835
{% endmacro %}
841836
""")
842837

@@ -866,130 +861,111 @@ class CircleMarker(Marker):
866861
See http://leafletjs.com/reference-1.2.0.html#path for more otions.
867862
868863
"""
869-
def __init__(self, location, radius=10, popup=None, **kw):
864+
def __init__(self, location, radius=10, popup=None, tooltip=None, **kw):
870865
super(CircleMarker, self).__init__(location=location, popup=popup)
871866
self._name = 'CircleMarker'
872-
options = _parse_path(**kw)
867+
self.tooltip = tooltip
873868

869+
options = _parse_path(**kw)
874870
options.update({'radius': radius})
875871
self.options = json.dumps(options, sort_keys=True, indent=2)
876872

877873
self._template = Template(u"""
878874
{% macro script(this, kwargs) %}
879875
var {{this.get_name()}} = L.circleMarker(
880-
[{{this.location[0]}},{{this.location[1]}}],
876+
[{{this.location[0]}}, {{this.location[1]}}],
881877
{{ this.options }}
882-
).addTo({{this._parent.get_name()}});
878+
)
879+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
880+
.addTo({{this._parent.get_name()}});
883881
{% endmacro %}
884882
""")
885883

886884

887-
class RectangleMarker(Marker):
888-
def __init__(self, bounds, color='black', weight=1, fill_color='black',
889-
fill_opacity=0.6, popup=None):
890-
"""
891-
Creates a RectangleMarker object for plotting on a Map.
892-
893-
Parameters
894-
----------
895-
bounds: tuple or list, default None
896-
Latitude and Longitude of Marker (southWest and northEast)
897-
color: string, default ('black')
898-
Edge color of a rectangle.
899-
weight: float, default (1)
900-
Edge line width of a rectangle.
901-
fill_color: string, default ('black')
902-
Fill color of a rectangle.
903-
fill_opacity: float, default (0.6)
904-
Fill opacity of a rectangle.
905-
popup: string or folium.Popup, default None
906-
Input text or visualization for object.
907-
908-
Returns
909-
-------
910-
folium.features.RectangleMarker object
911-
912-
Example
913-
-------
914-
>>> RectangleMarker(
915-
... bounds=[[35.681, 139.766], [35.691, 139.776]],
916-
... color='blue', fill_color='red', popup='Tokyo, Japan'
917-
... )
885+
class Rectangle(Marker):
886+
"""
887+
Creates a Rectangle Marker object for plotting on a Map.
888+
889+
Parameters
890+
----------
891+
bounds: tuple or list, default None
892+
Latitude and Longitude of Marker (southWest and northEast)
893+
color: string, default ('black')
894+
Edge color of a rectangle.
895+
weight: float, default (1)
896+
Edge line width of a rectangle.
897+
fill_color: string, default ('black')
898+
Fill color of a rectangle.
899+
fill_opacity: float, default (0.6)
900+
Fill opacity of a rectangle.
901+
popup: string or folium.Popup, default None
902+
Input text or visualization for object.
903+
904+
See http://leafletjs.com/reference-1.2.0.html#path for more otions.
905+
906+
"""
907+
def __init__(self, bounds, popup=None, tooltip=None, **kwargs):
908+
super(Rectangle, self).__init__(location=bounds, popup=popup)
909+
self._name = 'rectangle'
910+
self.tooltip = tooltip
911+
912+
options = _parse_path(**kwargs)
913+
self.options = json.dumps(options, sort_keys=True, indent=2)
918914

919-
"""
920-
super(RectangleMarker, self).__init__(bounds, popup=popup)
921-
self._name = 'RectangleMarker'
922-
self.color = color
923-
self.weight = weight
924-
self.fill_color = fill_color
925-
self.fill_opacity = fill_opacity
926915
self._template = Template(u"""
927916
{% macro script(this, kwargs) %}
917+
928918
var {{this.get_name()}} = L.rectangle(
929-
[[{{this.location[0]}},{{this.location[1]}}],
930-
[{{this.location[2]}},{{this.location[3]}}]],
931-
{
932-
color: '{{ this.color }}',
933-
fillColor: '{{ this.fill_color }}',
934-
fillOpacity: {{ this.fill_opacity }},
935-
weight: {{ this.weight }}
936-
}).addTo({{this._parent.get_name()}});
919+
{{this.location}},
920+
{{ this.options }}
921+
)
922+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
923+
.addTo({{this._parent.get_name()}});
937924
938925
{% endmacro %}
939926
""")
940927

941928

942-
class PolygonMarker(Marker):
943-
def __init__(self, locations, color='black', weight=1, fill_color='black',
944-
fill_opacity=0.6, popup=None):
945-
"""
946-
Creates a PolygonMarker object for plotting on a Map.
947-
948-
Parameters
949-
----------
950-
locations: tuple or list, default None
951-
Latitude and Longitude of Polygon
952-
color: string, default ('black')
953-
Edge color of a polygon.
954-
weight: float, default (1)
955-
Edge line width of a polygon.
956-
fill_color: string, default ('black')
957-
Fill color of a polygon.
958-
fill_opacity: float, default (0.6)
959-
Fill opacity of a polygon.
960-
popup: string or folium.Popup, default None
961-
Input text or visualization for object.
962-
963-
Returns
964-
-------
965-
folium.features.Polygon object
966-
967-
Examples
968-
--------
969-
>>> locations = [[35.6762, 139.7795],
970-
... [35.6718, 139.7831],
971-
... [35.6767, 139.7868],
972-
... [35.6795, 139.7824],
973-
... [35.6787, 139.7791]]
974-
>>> Polygon(locations, color='blue', weight=10, fill_color='red',
975-
... fill_opacity=0.5, popup='Tokyo, Japan'))
929+
class Polygon(Marker):
930+
"""
931+
Creates a Polygon Marker object for plotting on a Map.
932+
933+
Parameters
934+
----------
935+
locations: tuple or list, default None
936+
Latitude and Longitude of Polygon
937+
color: string, default ('black')
938+
Edge color of a polygon.
939+
weight: float, default (1)
940+
Edge line width of a polygon.
941+
fill_color: string, default ('black')
942+
Fill color of a polygon.
943+
fill_opacity: float, default (0.6)
944+
Fill opacity of a polygon.
945+
popup: string or folium.Popup, default None
946+
Input text or visualization for object.
947+
948+
See http://leafletjs.com/reference-1.2.0.html#path for more otions.
949+
950+
"""
951+
def __init__(self, locations, popup=None, tooltip=None, **kwargs):
952+
super(Polygon, self).__init__(locations, popup=popup)
953+
self._name = 'Polygon'
954+
self.tooltip = tooltip
955+
956+
options = _parse_path(**kwargs)
957+
self.options = json.dumps(options, sort_keys=True, indent=2)
976958

977-
"""
978-
super(PolygonMarker, self).__init__(locations, popup=popup)
979-
self._name = 'PolygonMarker'
980-
self.color = color
981-
self.weight = weight
982-
self.fill_color = fill_color
983-
self.fill_opacity = fill_opacity
984959
self._template = Template(u"""
985960
{% macro script(this, kwargs) %}
986-
var {{this.get_name()}} = L.polygon({{this.location}},
987-
{
988-
color: '{{ this.color }}',
989-
fillColor: '{{ this.fill_color }}',
990-
fillOpacity: {{ this.fill_opacity }},
991-
weight: {{ this.weight }}
992-
}).addTo({{this._parent.get_name()}});
961+
962+
var {{this.get_name()}} = L.polygon(
963+
{{this.location}},
964+
{{ this.options }}
965+
)
966+
{% if this.tooltip %}.bindTooltip("{{this.tooltip.__str__()}}"){% endif %}
967+
.addTo({{this._parent.get_name()}});
968+
993969
{% endmacro %}
994970
""")
995971

0 commit comments

Comments
 (0)