Skip to content

Add minimap plugin #968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Oct 16, 2018
Merged
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Update leaflet to 1.3.4 (ocefpaf #939)
- More options (tms, opacity, kwargs) in TileLayer (mpickering #948)
- Add MousePosition plugin (btozer #916)
- Add Minimap plugin (talbertc-usgs #968)

Bug Fixes

Expand Down
241 changes: 241 additions & 0 deletions examples/MiniMap.ipynb

Large diffs are not rendered by default.

84 changes: 61 additions & 23 deletions examples/Plugins.ipynb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions folium/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from folium.plugins.timestamped_geo_json import TimestampedGeoJson
from folium.plugins.timestamped_wmstilelayer import TimestampedWmsTileLayers
from folium.plugins.search import Search
from folium.plugins.minimap import MiniMap

__all__ = [
'BeautifyIcon',
Expand All @@ -50,4 +51,5 @@
'TimestampedGeoJson',
'TimestampedWmsTileLayers',
'Search',
'MiniMap',
]
121 changes: 121 additions & 0 deletions folium/plugins/minimap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*-

from __future__ import (absolute_import, division, print_function)

import json

from branca.element import CssLink, Figure, JavascriptLink, MacroElement
from folium.raster_layers import TileLayer

from jinja2 import Template


class MiniMap(MacroElement):
"""Add a minimap (locator) to an existing map.

Uses the Leaflet plugin by Norkart under BSD 2-Clause "Simplified" License.
https://github.com/Norkart/Leaflet-MiniMap

Parameters
----------
tile_layer : folium TileLayer object or str, default None
Provide a folium TileLayer object or the wanted tiles as string.
If not provided it will use the default of 'TileLayer', currently
OpenStreetMap.
position : str, default 'bottomright'
The standard Control position parameter for the widget.
width : int, default 150
The width of the minimap in pixels.
height : int, default 150
The height of the minimap in pixels.
collapsed_width : int, default 25
The width of the toggle marker and the minimap when collapsed in pixels.
collapsed_height : int, default 25
The height of the toggle marker and the minimap when collapsed
zoom_level_offset : int, default -5
The offset applied to the zoom in the minimap compared to the zoom of
the main map. Can be positive or negative.
zoom_level_fixed : int, default None
Overrides the offset to apply a fixed zoom level to the minimap
regardless of the main map zoom.
Set it to any valid zoom level, if unset zoom_level_offset is used
instead.
center_fixed : bool, default False
Applies a fixed position to the minimap regardless of the main map's
view / position. Prevents panning the minimap, but does allow zooming
(both in the minimap and the main map).
If the minimap is zoomed, it will always zoom around the centerFixed
point. You can pass in a LatLng-equivalent object.
zoom_animation : bool, default False
Sets whether the minimap should have an animated zoom.
(Will cause it to lag a bit after the movement of the main map.)
toggle_display : bool, default False
Sets whether the minimap should have a button to minimise it.
auto_toggle_display : bool, default False
Sets whether the minimap should hide automatically
if the parent map bounds does not fit within the minimap bounds.
Especially useful when 'zoomLevelFixed' is set.
minimized : bool, default False
Sets whether the minimap should start in a minimized position.

Examples
--------
>>> MiniMap(tile_layer='Stamen WaterColor', position='bottomleft')
"""

_template = Template("""
{% macro script(this, kwargs) %}

var {{ this.tile_layer.get_name() }} = L.tileLayer(
'{{ this.tile_layer.tiles }}',
{{ this.tile_layer.options }} );

var {{ this.get_name() }} = new L.Control.MiniMap( {{this.tile_layer.get_name()}},
{{ this.options }});
{{ this._parent.get_name() }}.addControl({{ this.get_name() }});

{% endmacro %}
""") # noqa

def __init__(self, tile_layer=None, position='bottomright', width=150,
height=150, collapsed_width=25, collapsed_height=25,
zoom_level_offset=-5, zoom_level_fixed=None,
center_fixed=False, zoom_animation=False,
toggle_display=False, auto_toggle_display=False,
minimized=False):

super(MiniMap, self).__init__()
self._name = 'MiniMap'

if tile_layer is None:
self.tile_layer = TileLayer()
elif isinstance(tile_layer, TileLayer):
self.tile_layer = tile_layer
else:
self.tile_layer = TileLayer(tile_layer)

options = {
'position': position,
'width': width,
'height': height,
'collapsedWidth': collapsed_width,
'collapsedHeight': collapsed_height,
'zoomLevelOffset': zoom_level_offset,
'zoomLevelFixed': zoom_level_fixed,
'centerFixed': center_fixed,
'zoomAnimation': zoom_animation,
'toggleDisplay': toggle_display,
'autoToggleDisplay': auto_toggle_display,
'minimized': minimized,
}
self.options = json.dumps(options, sort_keys=True, indent=2)

def render(self, **kwargs):
figure = self.get_root()
assert isinstance(figure, Figure), ('You cannot render this Element '
'if it is not in a Figure.')
super(MiniMap, self).render()

figure.header.add_child(JavascriptLink('https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.js')) # noqa

figure.header.add_child(CssLink('https://cdnjs.cloudflare.com/ajax/libs/leaflet-minimap/3.6.1/Control.MiniMap.css')) # noqa
32 changes: 32 additions & 0 deletions tests/plugins/test_minimap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-

"""
Test MiniMap
---------------
"""

from __future__ import (absolute_import, division, print_function)

import folium

from folium import plugins


def test_minimap():
m = folium.Map(location=(30, 20), zoom_start=4)

minimap = plugins.MiniMap()
m.add_child(minimap)

out = m._parent.render()

# Verify that a new minimap is getting created.
assert 'new L.Control.MiniMap' in out

m = folium.Map(location=(30, 20), zoom_start=4)
minimap = plugins.MiniMap(tile_layer="Stamen Toner")
minimap.add_to(m)

out = m._parent.render()
# verify that Stamen Toner tiles are being used
assert 'https://stamen-tiles' in out