Skip to content

Commit 51aed1d

Browse files
committed
adding Leaflet.timeDimension support for WmsTileLayers as well as additional kwargs as a way to support non-standard WMS request parameters
1 parent 89c76a0 commit 51aed1d

3 files changed

Lines changed: 152 additions & 2 deletions

File tree

folium/features.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,18 @@ class WmsTileLayer(Layer):
5151
Adds the layer as an optional overlay (True) or the base layer (False).
5252
control : bool, default True
5353
Whether the Layer will be included in LayerControls
54+
**kwargs : additional keyword arguments
55+
Passed through to the underlying tileLayer.wms object and can be used
56+
for setting extra tileLayer.wms parameters or as extra parameters in
57+
the WMS request.
5458
5559
For more information see:
5660
http://leafletjs.com/reference.html#tilelayer-wms
5761
5862
"""
5963
def __init__(self, url, name=None, layers=None, styles=None, format=None,
6064
transparent=True, version='1.1.1', attr=None, overlay=True,
61-
control=True):
65+
control=True, **kwargs):
6266
super(WmsTileLayer, self).__init__(overlay=overlay, control=control, name=name) # noqa
6367
self.url = url
6468
self.attribution = attr if attr is not None else ''
@@ -68,11 +72,15 @@ def __init__(self, url, name=None, layers=None, styles=None, format=None,
6872
self.format = format if format else 'image/jpeg'
6973
self.transparent = transparent
7074
self.version = version
75+
self.kwargs = kwargs
7176
self._template = Template(u"""
7277
{% macro script(this, kwargs) %}
7378
var {{this.get_name()}} = L.tileLayer.wms(
7479
'{{ this.url }}',
7580
{
81+
{% for key, value in this.kwargs.items() %}
82+
{{key}}: '{{ value }}',
83+
{% endfor %}
7684
layers: '{{ this.layers }}',
7785
styles: '{{ this.styles }}',
7886
format: '{{ this.format }}',

folium/plugins/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from .fullscreen import Fullscreen
1717
from .polyline_text_path import PolyLineTextPath
1818
from .float_image import FloatImage
19+
from .timestamped_wmstilelayer import TimestampedWmsTileLayer
1920

2021
__all__ = [
2122
'MarkerCluster',
@@ -27,5 +28,6 @@
2728
'ImageOverlay',
2829
'Fullscreen',
2930
'PolyLineTextPath',
30-
'FloatImage'
31+
'FloatImage',
32+
'TimestampedWmsTileLayer'
3133
]
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
TimestampedGeoJson plugin
4+
--------------
5+
6+
Add a timestamped geojson feature collection on a folium map.
7+
This is based on Leaflet.TimeDimension.
8+
9+
https://github.com/socib/Leaflet.TimeDimension
10+
11+
A geo-json is timestamped if:
12+
* it contains only features of types LineString, MultiPoint,
13+
MultiLineString and MultiPolygon.
14+
* each feature has a "times" property with the same length as the
15+
coordinates array.
16+
* each element of each "times" property is a timestamp in ms since epoch,
17+
or in ISO string. Eventually, you may have Point features with a
18+
"times" property being an array of length 1.
19+
20+
"""
21+
22+
from jinja2 import Template
23+
24+
from ..map import Layer
25+
26+
27+
class TimestampedWmsTileLayer(Layer):
28+
def __init__(self, data, transition_time=200, loop=False, auto_play=False,
29+
period="P1D"):
30+
"""Creates a TimestampedWmsTileLayer subclass of Layer that takes a
31+
WmsTileLayer and adds time control with the Leaflet.TimeDimension
32+
plugin.
33+
34+
Parameters
35+
----------
36+
data: WmsTileLayer.
37+
The WmsTileLayer that you want to add time support to.
38+
39+
* Should be created like a typical WmsTileLayer and added to the map
40+
before being passed to this class.
41+
42+
examples :
43+
# Create WmsTileLayer
44+
w = features.WmsTileLayer(
45+
"http://this.wms.server/ncWMS/wms",
46+
name="Test WMS Data",
47+
styles="",
48+
format="image/png",
49+
transparent=True,
50+
layers="test_data",
51+
COLORSCALERANGE="0,10",
52+
)
53+
# Add to map
54+
w.add_to(m)
55+
56+
# Add WmsTileLayer to time control
57+
time = plugins.TimestampedWmsTileLayer(w)
58+
time.add_to(m)
59+
60+
transition_time : int, default 200.
61+
The duration in ms of a transition from between timestamps.
62+
loop : bool, default False
63+
Whether the animation shall loop, default is to reduce load on WMS
64+
services.
65+
auto_play : bool, default False
66+
Whether the animation shall start automatically at startup, default
67+
is to reduce load on WMS services.
68+
period : str, default "P1D"
69+
Used to construct the array of available times starting
70+
from the first available time. Format: ISO8601 Duration
71+
ex: "P1M" -> 1/month
72+
"P1D" -> 1/day
73+
"PT1H" -> 1/hour
74+
"PT1M" -> 1/minute
75+
Note: this seems to be overridden by the WMS Tile Layer
76+
GetCapabilities.
77+
"""
78+
super(TimestampedWmsTileLayer, self).__init__(overlay=True,
79+
control=data.control,
80+
name=data.layer_name)
81+
self._name = 'TimestampedWmsTileLayer'
82+
83+
self.transition_time = int(transition_time)
84+
self.loop = bool(loop)
85+
self.auto_play = bool(auto_play)
86+
self.period = period
87+
self.layer = data
88+
self._template = Template("""
89+
print kwargs
90+
{% macro script(this, kwargs) %}
91+
{{this._parent.get_name()}}.timeDimension = L.timeDimension({period:"{{this.period}}"});
92+
{{this._parent.get_name()}}.timeDimensionControl = L.control.timeDimension({
93+
position: 'bottomleft',
94+
autoPlay: {{'true' if this.auto_play else 'false'}},
95+
playerOptions: {
96+
transitionTime: {{this.transition_time}},
97+
loop: {{'true' if this.loop else 'false'}}}
98+
});
99+
{{this._parent.get_name()}}.addControl({{this._parent.get_name()}}.timeDimensionControl);
100+
101+
102+
var {{this.get_name()}} = L.timeDimension.layer.wms({{ this.layer.get_name() }},
103+
{updateTimeDimension: true,
104+
wmsVersion: '{{ this.layer.version }}',
105+
}
106+
).addTo({{this._parent.get_name()}});
107+
{% endmacro %}
108+
""")
109+
110+
111+
def render(self, **kwargs):
112+
super(TimestampedWmsTileLayer, self).render()
113+
114+
figure = self.get_root()
115+
assert isinstance(figure, Figure), ("You cannot render this Element "
116+
"if it's not in a Figure.")
117+
118+
figure.header.add_child(
119+
JavascriptLink("https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"), # noqa
120+
name='jquery2.0.0')
121+
122+
figure.header.add_child(
123+
JavascriptLink("https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"), # noqa
124+
name='jqueryui1.10.2')
125+
126+
figure.header.add_child(
127+
JavascriptLink("https://rawgit.com/nezasa/iso8601-js-period/master/iso8601.min.js"), # noqa
128+
name='iso8601')
129+
130+
figure.header.add_child(
131+
JavascriptLink("https://rawgit.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.min.js"), # noqa
132+
name='leaflet.timedimension')
133+
134+
figure.header.add_child(
135+
CssLink("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css"), # noqa
136+
name='highlight.js_css')
137+
138+
figure.header.add_child(
139+
CssLink("http://apps.socib.es/Leaflet.TimeDimension/dist/leaflet.timedimension.control.min.css"), # noqa
140+
name='leaflet.timedimension_css')

0 commit comments

Comments
 (0)