Skip to content

Commit b03b81e

Browse files
Conengmoocefpaf
authored andcommitted
Tilesets native zoom (#792)
* Added max_native_zoom keyword
1 parent 106d829 commit b03b81e

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

folium/folium.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ class Map(MacroElement):
105105
Minimum allowed zoom level for the tile layer that is created.
106106
max_zoom: int, default 18
107107
Maximum allowed zoom level for the tile layer that is created.
108+
max_native_zoom: int, default None
109+
The highest zoom level at which the tile server can provide tiles.
110+
If provided you can zoom in past this level. Else tiles will turn grey.
108111
zoom_start: int, default 10
109112
Initial zoom level for the map.
110113
attr: string, default None
@@ -166,7 +169,7 @@ class Map(MacroElement):
166169
def __init__(self, location=None, width='100%', height='100%',
167170
left='0%', top='0%', position='relative',
168171
tiles='OpenStreetMap', API_key=None, max_zoom=18, min_zoom=0,
169-
zoom_start=10, world_copy_jump=False,
172+
max_native_zoom=None, zoom_start=10, world_copy_jump=False,
170173
no_wrap=False, attr=None, min_lat=-90, max_lat=90,
171174
min_lon=-180, max_lon=180, max_bounds=False,
172175
detect_retina=False, crs='EPSG3857', control_scale=False,
@@ -216,7 +219,7 @@ def __init__(self, location=None, width='100%', height='100%',
216219
if tiles:
217220
self.add_tile_layer(
218221
tiles=tiles, min_zoom=min_zoom, max_zoom=max_zoom,
219-
no_wrap=no_wrap, attr=attr,
222+
max_native_zoom=max_native_zoom, no_wrap=no_wrap, attr=attr,
220223
API_key=API_key, detect_retina=detect_retina,
221224
subdomains=subdomains
222225
)
@@ -312,7 +315,7 @@ def _repr_png_(self):
312315

313316
def add_tile_layer(self, tiles='OpenStreetMap', name=None,
314317
API_key=None, max_zoom=18, min_zoom=0,
315-
attr=None, active=False,
318+
max_native_zoom=None, attr=None, active=False,
316319
detect_retina=False, no_wrap=False, subdomains='abc',
317320
**kwargs):
318321
"""
@@ -321,6 +324,7 @@ def add_tile_layer(self, tiles='OpenStreetMap', name=None,
321324
"""
322325
tile_layer = TileLayer(tiles=tiles, name=name,
323326
min_zoom=min_zoom, max_zoom=max_zoom,
327+
max_native_zoom=max_native_zoom,
324328
attr=attr, API_key=API_key,
325329
detect_retina=detect_retina,
326330
subdomains=subdomains,

folium/raster_layers.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,22 @@ class TileLayer(Layer):
3131
tiles: str, default 'OpenStreetMap'
3232
Map tileset to use. Can choose from this list of built-in tiles:
3333
- "OpenStreetMap"
34-
- "Mapbox Bright" (Limited levels of zoom for free tiles)
35-
- "Mapbox Control Room" (Limited levels of zoom for free tiles)
36-
- "Stamen" (Terrain, Toner, and Watercolor)
34+
- "Stamen Terrain", "Stamen Toner", "Stamen Watercolor"
35+
- "CartoDB positron", "CartoDB dark_matter"
36+
- "Mapbox Bright", "Mapbox Control Room" (Limited zoom)
3737
- "Cloudmade" (Must pass API key)
3838
- "Mapbox" (Must pass API key)
39-
- "CartoDB" (positron and dark_matter)
4039
4140
You can pass a custom tileset to Folium by passing a Leaflet-style
4241
URL to the tiles parameter: ``http://{s}.yourtiles.com/{z}/{x}/{y}.png``
42+
You must then also provide attribution, use the `attr` keyword.
4343
min_zoom: int, default 0
4444
Minimum allowed zoom level for this tile layer.
4545
max_zoom: int, default 18
4646
Maximum allowed zoom level for this tile layer.
47+
max_native_zoom: int, default None
48+
The highest zoom level at which the tile server can provide tiles.
49+
If provided you can zoom in past this level. Else tiles will turn grey.
4750
attr: string, default None
4851
Map tile attribution; only required if passing custom tile URL.
4952
API_key: str, default None
@@ -63,8 +66,8 @@ class TileLayer(Layer):
6366
6467
"""
6568
def __init__(self, tiles='OpenStreetMap', min_zoom=0, max_zoom=18,
66-
attr=None, API_key=None, detect_retina=False,
67-
name=None, overlay=False,
69+
max_native_zoom=None, attr=None, API_key=None,
70+
detect_retina=False, name=None, overlay=False,
6871
control=True, no_wrap=False, subdomains='abc'):
6972
self.tile_name = (name if name is not None else
7073
''.join(tiles.lower().strip().split()))
@@ -73,33 +76,31 @@ def __init__(self, tiles='OpenStreetMap', min_zoom=0, max_zoom=18,
7376
self._name = 'TileLayer'
7477
self._env = ENV
7578

76-
options = {
77-
'minZoom': min_zoom,
78-
'maxZoom': max_zoom,
79-
'noWrap': no_wrap,
80-
'attribution': attr,
81-
'subdomains': subdomains,
82-
'detectRetina': detect_retina,
83-
}
79+
options = {'minZoom': min_zoom,
80+
'maxZoom': max_zoom,
81+
'maxNativeZoom': max_native_zoom or max_zoom,
82+
'noWrap': no_wrap,
83+
'attribution': attr,
84+
'subdomains': subdomains,
85+
'detectRetina': detect_retina}
8486
self.options = json.dumps(options, sort_keys=True, indent=2)
8587

86-
self.tiles = ''.join(tiles.lower().strip().split())
87-
if self.tiles in ('cloudmade', 'mapbox') and not API_key:
88+
tiles_flat = ''.join(tiles.lower().strip().split())
89+
if tiles_flat in ('cloudmade', 'mapbox') and not API_key:
8890
raise ValueError('You must pass an API key if using Cloudmade'
8991
' or non-default Mapbox tiles.')
9092
templates = list(self._env.list_templates(
9193
filter_func=lambda x: x.startswith('tiles/')))
92-
tile_template = 'tiles/'+self.tiles+'/tiles.txt'
93-
attr_template = 'tiles/'+self.tiles+'/attr.txt'
94+
tile_template = 'tiles/' + tiles_flat + '/tiles.txt'
95+
attr_template = 'tiles/' + tiles_flat + '/attr.txt'
9496

9597
if tile_template in templates and attr_template in templates:
9698
self.tiles = self._env.get_template(tile_template).render(API_key=API_key) # noqa
9799
self.attr = self._env.get_template(attr_template).render()
98100
else:
99101
self.tiles = tiles
100102
if not attr:
101-
raise ValueError('Custom tiles must'
102-
' also be passed an attribution.')
103+
raise ValueError('Custom tiles must have an attribution.')
103104
if isinstance(attr, binary_type):
104105
attr = text_type(attr, 'utf8')
105106
self.attr = attr
@@ -111,7 +112,7 @@ def __init__(self, tiles='OpenStreetMap', min_zoom=0, max_zoom=18,
111112
{{ this.options }}
112113
).addTo({{this._parent.get_name()}});
113114
{% endmacro %}
114-
""") # noqa
115+
""")
115116

116117

117118
class WmsTileLayer(Layer):

tests/test_raster_layers.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
"""
4-
Test ImageOverlay
4+
Test raster_layers
55
-----------------
66
77
"""
@@ -36,6 +36,15 @@ def test_tile_layer():
3636
assert bounds == [[None, None], [None, None]], bounds
3737

3838

39+
def _is_working_zoom_level(zoom, tiles, session):
40+
"""Check if the zoom level works for the given tileset."""
41+
url = tiles.format(s='a', x=0, y=0, z=zoom)
42+
response = session.get(url, timeout=5)
43+
if response.status_code < 400:
44+
return True
45+
return False
46+
47+
3948
def test_custom_tile_subdomains():
4049
"""Test custom tile subdomains."""
4150

0 commit comments

Comments
 (0)