Skip to content

Commit 4c1515d

Browse files
author
Martin Journois
committed
Fix test_fit_bounds
1 parent 0d2eece commit 4c1515d

4 files changed

Lines changed: 100 additions & 69 deletions

File tree

folium/folium.py

Lines changed: 34 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from folium.six import text_type, binary_type#, iteritems
2525
from .map import Map as _Map
2626
from .element import Element, Figure, JavascriptLink, CssLink, Div, MacroElement
27-
from .map import Map, TileLayer, Icon, Marker, Popup
27+
from .map import Map, TileLayer, Icon, Marker, Popup, FitBounds
2828
from .features import WmsTileLayer, RegularPolygonMarker, Vega, GeoJson, GeoJsonStyle, MarkerCluster, DivIcon,\
2929
CircleMarker, LatLngPopup, ClickForMarker, ColorScale, TopoJson, PolyLine, MultiPolyLine
3030
from .utilities import color_brewer
@@ -477,22 +477,6 @@ def multiline(self, locations, line_color=None, line_opacity=None,
477477

478478
self.add_children(p)
479479

480-
# count = self.mark_cnt['multiline']
481-
#
482-
# multiline_temp = self.env.get_template('multi_polyline.js')
483-
#
484-
# multiline_opts = {'color': line_color, 'weight': line_weight,
485-
# 'opacity': line_opacity}
486-
#
487-
# varname = 'multiline_{}'.format(count)
488-
# multiline_rendered = multiline_temp.render({'multiline': varname,
489-
# 'locations': locations,
490-
# 'options': multiline_opts})
491-
#
492-
# add_multiline = 'map.addLayer({});'.format(varname)
493-
# append = (multiline_rendered, add_multiline)
494-
# self.template_vars.setdefault('multilines', []).append(append)
495-
#
496480
# @iter_obj('circle')
497481
def circle_marker(self, location=None, radius=500, popup=None,
498482
line_color='black', fill_color='black',
@@ -632,50 +616,39 @@ def click_for_marker(self, popup=None):
632616
FutureWarning, stacklevel=2)
633617
self.add_children(ClickForMarker(popup=popup))
634618

635-
# def fit_bounds(self, bounds, padding_top_left=None,
636-
# padding_bottom_right=None, padding=None, max_zoom=None):
637-
# """Fit the map to contain a bounding box with the maximum zoom level possible.
638-
#
639-
# Parameters
640-
# ----------
641-
# bounds: list of (latitude, longitude) points
642-
# Bounding box specified as two points [southwest, northeast]
643-
# padding_top_left: (x, y) point, default None
644-
# Padding in the top left corner. Useful if some elements in
645-
# the corner, such as controls, might obscure objects you're zooming
646-
# to.
647-
# padding_bottom_right: (x, y) point, default None
648-
# Padding in the bottom right corner.
649-
# padding: (x, y) point, default None
650-
# Equivalent to setting both top left and bottom right padding to
651-
# the same value.
652-
# max_zoom: int, default None
653-
# Maximum zoom to be used.
654-
#
655-
# Example
656-
# -------
657-
# >>> map.fit_bounds([[52.193636, -2.221575], [52.636878, -1.139759]])
658-
#
659-
# """
660-
# options = {
661-
# 'paddingTopLeft': padding_top_left,
662-
# 'paddingBottomRight': padding_bottom_right,
663-
# 'padding': padding,
664-
# 'maxZoom': max_zoom,
665-
# }
666-
# fit_bounds_options = {}
667-
# for key, opt in options.items():
668-
# if opt:
669-
# fit_bounds_options[key] = opt
670-
# fit_bounds = self.env.get_template('fit_bounds.js')
671-
# fit_bounds_str = fit_bounds.render({
672-
# 'bounds': json.dumps(bounds),
673-
# 'fit_bounds_options': json.dumps(fit_bounds_options,
674-
# sort_keys=True),
675-
# })
676-
#
677-
# self.template_vars.update({'fit_bounds': fit_bounds_str})
678-
#
619+
def fit_bounds(self, bounds, padding_top_left=None,
620+
padding_bottom_right=None, padding=None, max_zoom=None):
621+
"""Fit the map to contain a bounding box with the maximum zoom level possible.
622+
623+
Parameters
624+
----------
625+
bounds: list of (latitude, longitude) points
626+
Bounding box specified as two points [southwest, northeast]
627+
padding_top_left: (x, y) point, default None
628+
Padding in the top left corner. Useful if some elements in
629+
the corner, such as controls, might obscure objects you're zooming
630+
to.
631+
padding_bottom_right: (x, y) point, default None
632+
Padding in the bottom right corner.
633+
padding: (x, y) point, default None
634+
Equivalent to setting both top left and bottom right padding to
635+
the same value.
636+
max_zoom: int, default None
637+
Maximum zoom to be used.
638+
639+
Example
640+
-------
641+
>>> map.fit_bounds([[52.193636, -2.221575], [52.636878, -1.139759]])
642+
643+
"""
644+
self.add_children(FitBounds(bounds,
645+
padding_top_left=padding_top_left,
646+
padding_bottom_right=padding_bottom_right,
647+
padding=padding,
648+
max_zoom=max_zoom,
649+
)
650+
)
651+
679652
def add_plugin(self, plugin):
680653
"""Adds a plugin to the map.
681654

folium/map.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Classes for drawing maps.
77
"""
88
import warnings
9+
import json
910

1011
from jinja2 import Template
1112

@@ -333,3 +334,50 @@ def render(self, **kwargs):
333334

334335
figure.script.add_children(Element(\
335336
self._template.render(this=self, kwargs=kwargs)), name=self.get_name())
337+
338+
class FitBounds(MacroElement):
339+
def __init__(self, bounds, padding_top_left=None,
340+
padding_bottom_right=None, padding=None, max_zoom=None):
341+
"""Fit the map to contain a bounding box with the maximum zoom level possible.
342+
343+
Parameters
344+
----------
345+
bounds: list of (latitude, longitude) points
346+
Bounding box specified as two points [southwest, northeast]
347+
padding_top_left: (x, y) point, default None
348+
Padding in the top left corner. Useful if some elements in
349+
the corner, such as controls, might obscure objects you're zooming
350+
to.
351+
padding_bottom_right: (x, y) point, default None
352+
Padding in the bottom right corner.
353+
padding: (x, y) point, default None
354+
Equivalent to setting both top left and bottom right padding to
355+
the same value.
356+
max_zoom: int, default None
357+
Maximum zoom to be used.
358+
359+
"""
360+
super(FitBounds, self).__init__()
361+
self._name = 'FitBounds'
362+
self.bounds = json.loads(json.dumps(bounds))
363+
options = {
364+
'maxZoom': max_zoom,
365+
'paddingTopLeft': padding_top_left,
366+
'paddingBottomRight': padding_bottom_right,
367+
'padding': padding,
368+
}
369+
self.fit_bounds_options = json.dumps({key:val for key,val in options.items() if val},
370+
sort_keys=True)
371+
372+
self._template = Template(u"""
373+
{% macro script(this, kwargs) %}
374+
{% if this.autobounds %}
375+
var autobounds = L.featureGroup({{ this.features }}).getBounds()
376+
{% endif %}
377+
378+
{{this._parent.get_name()}}.fitBounds(
379+
{% if this.bounds %}{{ this.bounds }}{% else %}"autobounds"{% endif %},
380+
{{ this.fit_bounds_options }}
381+
);
382+
{% endmacro %}
383+
""")

folium/templates/fit_bounds.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var autobounds = L.featureGroup({{ features }}).getBounds()
55
{% endif %}
66
{% endif %}
77
{% if bounds %}
8-
map.fitBounds({{ bounds }},
8+
{{this._parent.get_name()}}.fitBounds({{ bounds }},
99
{{ fit_bounds_options }}
1010
);
1111
{% endif %}

tests/test_folium.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from folium.six import PY3
1919
from folium.plugins import ScrollZoomToggler, MarkerCluster
2020
from folium.element import Html
21-
from folium.map import Popup, Marker, Icon
21+
from folium.map import Popup, Marker, Icon, FitBounds
2222
from folium.features import DivIcon, CircleMarker, LatLngPopup, GeoJson,\
2323
GeoJsonStyle, ColorScale, TopoJson, PolyLine, MultiPolyLine
2424

@@ -606,25 +606,35 @@ def test_multi_polyline(self):
606606
def test_fit_bounds(self):
607607
"""Test fit_bounds."""
608608
bounds = ((52.193636, -2.221575), (52.636878, -1.139759))
609+
610+
self.setup()
611+
self.map.fit_bounds(bounds)
612+
fitbounds = [val for key,val in self.map._children.items() if isinstance(val,FitBounds)][0]
613+
out = self.map._parent.render()
614+
609615
fit_bounds_tpl = self.env.get_template('fit_bounds.js')
610616
fit_bounds_rendered = fit_bounds_tpl.render({
611617
'bounds': json.dumps(bounds),
618+
'this' : fitbounds,
612619
'fit_bounds_options': {}, })
613620

614-
self.map.fit_bounds(bounds)
615-
assert self.map.template_vars['fit_bounds'] == fit_bounds_rendered
621+
assert ''.join(fit_bounds_rendered.split()) in ''.join(out.split())
622+
623+
self.setup()
624+
self.map.fit_bounds(bounds, max_zoom=15, padding=(3, 3))
625+
fitbounds = [val for key,val in self.map._children.items() if isinstance(val,FitBounds)][0]
626+
out = self.map._parent.render()
616627

617628
fit_bounds_tpl = self.env.get_template('fit_bounds.js')
618629
fit_bounds_rendered = fit_bounds_tpl.render({
619630
'bounds': json.dumps(bounds),
620631
'fit_bounds_options': json.dumps({'maxZoom': 15,
621632
'padding': (3, 3), },
622633
sort_keys=True),
623-
})
624-
625-
self.map.fit_bounds(bounds, max_zoom=15, padding=(3, 3))
634+
'this' : fitbounds,
635+
})
626636

627-
assert self.map.template_vars['fit_bounds'] == fit_bounds_rendered
637+
assert ''.join(fit_bounds_rendered.split()) in ''.join(out.split())
628638

629639
def test_image_overlay(self):
630640
"""Test image overlay."""

0 commit comments

Comments
 (0)