Skip to content

Commit 913cf29

Browse files
FabeGConengmo
authored andcommitted
Add PolyLineOffset Plugin (#1091)
Add PolyLineOffset Plugin See https://github.com/bbecquet/Leaflet.PolylineOffset
1 parent 43fd145 commit 913cf29

File tree

4 files changed

+509
-0
lines changed

4 files changed

+509
-0
lines changed

examples/plugin-PolyLineOffset.ipynb

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

folium/plugins/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"""
1010

1111
from folium.plugins.antpath import AntPath
12+
from folium.plugins.polyline_offset import PolyLineOffset
1213
from folium.plugins.beautify_icon import BeautifyIcon
1314
from folium.plugins.boat_marker import BoatMarker
1415
from folium.plugins.draw import Draw
@@ -50,6 +51,7 @@
5051
'MiniMap',
5152
'MousePosition',
5253
'PolyLineTextPath',
54+
'PolyLineOffset',
5355
'ScrollZoomToggler',
5456
'Search',
5557
'StripePattern',

folium/plugins/polyline_offset.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from __future__ import absolute_import, division, print_function
4+
5+
from branca.element import JavascriptLink
6+
7+
from folium.vector_layers import PolyLine
8+
9+
10+
class PolyLineOffset(PolyLine):
11+
"""
12+
Add offset capabilities to the PolyLine class.
13+
14+
This plugin adds to folium Polylines the ability to be drawn with a
15+
relative pixel offset, without modifying their actual coordinates. The offset
16+
value can be either negative or positive, for left- or right-side offset,
17+
and remains constant across zoom levels.
18+
19+
See :func:`folium.vector_layers.path_options` for the `Path` options.
20+
21+
Parameters
22+
----------
23+
locations: list of points (latitude, longitude)
24+
Latitude and Longitude of line (Northing, Easting)
25+
popup: str or folium.Popup, default None
26+
Input text or visualization for object displayed when clicking.
27+
tooltip: str or folium.Tooltip, optional
28+
Display a text when hovering over the object.
29+
offset: int, default 0
30+
Relative pixel offset to draw a line parallel to an existant one,
31+
at a fixed distance.
32+
**kwargs:
33+
Polyline options. See their Github page for the
34+
available parameters.
35+
36+
See https://github.com/bbecquet/Leaflet.PolylineOffset
37+
38+
Examples
39+
--------
40+
>>> plugins.PolyLineOffset([[58, -28], [53, -23]], color="#f00", opacity=1, offset=-5).add_to(m)
41+
>>> plugins.PolyLineOffset([[58, -28], [53, -23]], color="#080", opacity=1, offset=10).add_to(m)
42+
43+
"""
44+
45+
def __init__(self, locations, popup=None, tooltip=None, offset=0, **kwargs):
46+
super(PolyLineOffset, self).__init__(
47+
locations=locations, popup=popup, tooltip=tooltip, **kwargs
48+
)
49+
self._name = "PolyLineOffset"
50+
# Add PolyLineOffset offset.
51+
self.options.update({"offset": offset})
52+
53+
def render(self, **kwargs):
54+
super(PolyLineOffset, self).render()
55+
figure = self.get_root()
56+
figure.header.add_child(
57+
JavascriptLink("https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"), # noqa
58+
name="polylineoffset",
59+
)

tests/plugins/test_polyline_offset.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
Test PolyLineOffset
5+
-------------------
6+
"""
7+
8+
from __future__ import absolute_import, division, print_function
9+
10+
import folium
11+
from folium import plugins
12+
from folium.utilities import normalize
13+
14+
import pytest
15+
16+
17+
@pytest.mark.parametrize("offset", [0, 10, -10])
18+
def test_polylineoffset(offset):
19+
m = folium.Map([20.0, 0.0], zoom_start=3)
20+
21+
locations = [
22+
[59.355600, -31.99219],
23+
[55.178870, -42.89062],
24+
[47.754100, -43.94531],
25+
[38.272690, -37.96875],
26+
[27.059130, -41.13281],
27+
[16.299050, -36.56250],
28+
[8.4071700, -30.23437],
29+
[1.0546300, -22.50000],
30+
[-8.754790, -18.28125],
31+
[-21.61658, -20.03906],
32+
[-31.35364, -24.25781],
33+
[-39.90974, -30.93750],
34+
[-43.83453, -41.13281],
35+
[-47.75410, -49.92187],
36+
[-50.95843, -54.14062],
37+
[-55.97380, -56.60156],
38+
]
39+
40+
polylineoffset = plugins.PolyLineOffset(locations=locations, offset=offset)
41+
polylineoffset.add_to(m)
42+
43+
m._repr_html_()
44+
out = m._parent.render()
45+
46+
# We verify that the script import is present.
47+
script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"></script>' # noqa
48+
assert script in out
49+
50+
# We verify that the script part is correct.
51+
expected_rendered = """
52+
var {name} = L.polyline(
53+
{locations},
54+
{{
55+
"bubblingMouseEvents": true,
56+
"color": "#3388ff",
57+
"dashArray": null,
58+
"dashOffset": null,
59+
"fill": false,
60+
"fillColor": "#3388ff",
61+
"fillOpacity": 0.2,
62+
"fillRule": "evenodd",
63+
"lineCap": "round",
64+
"lineJoin": "round",
65+
"noClip": false,
66+
"offset": {offset},
67+
"opacity": 1.0,
68+
"smoothFactor": 1.0,
69+
"stroke": true,
70+
"weight": 3
71+
}}
72+
)
73+
.addTo({map});
74+
""".format(
75+
locations=locations,
76+
name=polylineoffset.get_name(),
77+
offset=offset,
78+
map=m.get_name(),
79+
)
80+
81+
rendered = polylineoffset._template.module.script(polylineoffset)
82+
assert normalize(expected_rendered) == normalize(rendered)
83+
84+
85+
def test_polylineoffset_without_offset():
86+
m = folium.Map([20.0, 0.0], zoom_start=3)
87+
88+
locations = [[59.355600, -31.99219], [55.178870, -42.89062]]
89+
90+
polylineoffset = plugins.PolyLineOffset(locations=locations)
91+
polylineoffset.add_to(m)
92+
93+
m._repr_html_()
94+
out = m._parent.render()
95+
96+
# We verify that the script import is present.
97+
script = '<script src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet.polylineoffset.min.js"></script>' # noqa
98+
assert script in out
99+
100+
# We verify that the script part is correct.
101+
expected_rendered = """
102+
var {name} = L.polyline(
103+
{locations},
104+
{{
105+
"bubblingMouseEvents": true,
106+
"color": "#3388ff",
107+
"dashArray": null,
108+
"dashOffset": null,
109+
"fill": false,
110+
"fillColor": "#3388ff",
111+
"fillOpacity": 0.2,
112+
"fillRule": "evenodd",
113+
"lineCap": "round",
114+
"lineJoin": "round",
115+
"noClip": false,
116+
"offset": 0,
117+
"opacity": 1.0,
118+
"smoothFactor": 1.0,
119+
"stroke": true,
120+
"weight": 3
121+
}}
122+
)
123+
.addTo({map});
124+
""".format(
125+
locations=locations, name=polylineoffset.get_name(), map=m.get_name()
126+
)
127+
128+
rendered = polylineoffset._template.module.script(polylineoffset)
129+
assert normalize(expected_rendered) == normalize(rendered)

0 commit comments

Comments
 (0)