Skip to content

Commit ad03fd7

Browse files
committed
Implemented the leaflet-realtime plugin
Based on: https://github.com/perliedman/leaflet-realtime
1 parent 0f4d57f commit ad03fd7

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

folium/plugins/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from folium.plugins.pattern import CirclePattern, StripePattern
2222
from folium.plugins.polyline_offset import PolyLineOffset
2323
from folium.plugins.polyline_text_path import PolyLineTextPath
24+
from folium.plugins.realtime import Realtime
2425
from folium.plugins.scroll_zoom_toggler import ScrollZoomToggler
2526
from folium.plugins.search import Search
2627
from folium.plugins.semicircle import SemiCircle
@@ -54,6 +55,7 @@
5455
"MousePosition",
5556
"PolyLineTextPath",
5657
"PolyLineOffset",
58+
"Realtime",
5759
"ScrollZoomToggler",
5860
"Search",
5961
"SemiCircle",

folium/plugins/realtime.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
from branca.element import MacroElement
2+
from jinja2 import Template
3+
4+
from folium.elements import JSCSSMixin
5+
from folium.utilities import parse_options, JsCode
6+
7+
8+
class Realtime(JSCSSMixin, MacroElement):
9+
"""Put realtime data on a Leaflet map: live tracking GPS units,
10+
sensor data or just about anything.
11+
12+
Based on: https://github.com/perliedman/leaflet-realtime
13+
14+
Parameters
15+
----------
16+
start : bool, default True
17+
Should automatic updates be enabled when layer is added
18+
on the map and stopped when layer is removed from the map
19+
interval : int, default 60000
20+
Automatic update interval, in milliseconds
21+
getFeatureId : function, default returns `feature.properties.id`
22+
Function to get an identifier uniquely identify a feature over time
23+
updateFeature : function
24+
Used to update an existing feature's layer;
25+
by default, points (markers) are updated, other layers are discarded
26+
and replaced with a new, updated layer.
27+
Allows to create more complex transitions,
28+
for example, when a feature is updated
29+
removeMissing : bool, default False
30+
Should missing features between updates been automatically
31+
removed from the layer
32+
33+
Other parameters are passed to the GeoJson layer, so you can pass
34+
`style`, `pointToLayer` and/or `onEachFeature`.
35+
36+
Examples
37+
--------
38+
>>> from folium.utilities import JsCode
39+
>>> m = folium.Map()
40+
>>> rt = Realtime("https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_geography_regions_elevation_points.geojson",
41+
... getFeatureId=JsCode("function(f) { return f.properties.name; }"),
42+
... interval=10000)
43+
>>> rt.add_to(m)
44+
"""
45+
46+
_template = Template(
47+
"""
48+
{% macro script(this, kwargs) %}
49+
var options = {{this.options|tojson}};
50+
{% for key, value in this.functions.items() %}
51+
options["{{key}}"] = {{ value }};
52+
{% endfor %}
53+
var {{ this.get_name() }} = new L.realtime(
54+
{{ this.src|tojson }},
55+
options
56+
);
57+
{{ this._parent.get_name() }}.addLayer(
58+
{{ this.get_name() }}._container);
59+
{% endmacro %}
60+
"""
61+
)
62+
63+
default_js = [
64+
(
65+
"Leaflet_Realtime_js",
66+
"https://cdnjs.cloudflare.com/ajax/libs/leaflet-realtime/2.2.0/leaflet-realtime.js", # NoQA
67+
)
68+
]
69+
70+
def __init__(self, src, **kwargs):
71+
super().__init__()
72+
self._name = "Realtime"
73+
self.src = src
74+
75+
# extract JsCode objects
76+
self.functions = {}
77+
for key, value in kwargs.items():
78+
if isinstance(value, JsCode):
79+
self.functions[key] = value.js_code
80+
81+
# and remove them from kwargs
82+
for key in self.functions:
83+
kwargs.pop(key)
84+
85+
# the container is special, as we
86+
# do not allow it to be set (yet)
87+
# from python
88+
self.options = parse_options(container=None, **kwargs)

folium/utilities.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,15 @@ def get_and_assert_figure_root(obj: Element) -> Figure:
410410
figure, Figure
411411
), "You cannot render this Element if it is not in a Figure."
412412
return figure
413+
414+
415+
# See:
416+
# https://github.com/andfanilo/streamlit-echarts/blob/master/streamlit_echarts/frontend/src/utils.js
417+
# Thanks andfanilo
418+
class JsCode:
419+
def __init__(self, js_code: str):
420+
"""Wrapper around a js function
421+
Args:
422+
js_code (str): javascript function code as str
423+
"""
424+
self.js_code = js_code

0 commit comments

Comments
 (0)