I made a folium map with lot of markers, each of them has a tooltip and a popup filled up with html formatted text. For every position defined by the markers I have additional geo datapoints which I want to display as a line / path / route / AntPath .. whatever. My Problem: The additional line should only appear when you click the marker (--> opens also the popup) or when hovering the marker (--> opens the tooltip).
I have no clue if it even is possible and hope to find some inspiration here
Here is an example which can be used in a jupyter. When you have installed pandas and folium it should work. I added some AntPath, but they never disappear as they are in the map. If you add them to the markercluster, the ants are not moving, if I add them to the popup everything is broken.
# imports
import pandas as pd
import folium
from folium.plugins import HeatMap, AntPath
# functions
def segmrk(latlng, geopath, pop='some text in the popup', tool='tooltiptext<br>in html'):
# define marker
style = ['bicycle', 'blue', '#FFFFFF']
# popup
iframe = folium.IFrame(pop, # html style text .. next step: change font!!
width=200,
height=200
)
fpop = folium.Popup(iframe)
#AntPath(geopath).add_to(fpop)
# marker
mrk = folium.Marker(location=latlng,
popup=fpop,
tooltip=tool,
icon=folium.Icon(icon=style[0], prefix='fa',
color=style[1],
icon_color=style[2]
),
)
return mrk
# sample data
df = pd.DataFrame()
df['geo'] = [[52.5172, 12.1024],[52.5172, 12.2024],[52.5172, 12.3024]]
df['geo_path'] = [[[52.5172, 12.1024],[52.6172, 12.1024],[52.7172, 12.1024],[52.7172, 12.1024]],
[[52.5172, 12.2024],[52.6172, 12.2024],[52.7172, 12.2024],[52.7172, 12.2024]],
[[52.5172, 12.3024],[52.6172, 12.3024],[52.7172, 12.3024],[52.7172, 12.3024]],
]
# define map
geo_start = [52.5172, 12.2024]
dmap = folium.Map(location=geo_start,
zoom_start=10,
tiles='OpenStreetMap'
)
mapstyle_2 = folium.raster_layers.TileLayer(tiles='CartoDB dark_matter',
name='dark',
overlay=False,
control=True,
show=True,
)
mapstyle_2.add_to(dmap)
# add full screen button
folium.plugins.Fullscreen().add_to(dmap)
# add layercontrol
# markergroups in layercontrol
mc = folium.plugins.MarkerCluster(name='Segment Markers',
overlay=True,
control=True,
show=True,
disableClusteringAtZoom=10
)
mc.add_to(dmap)
mcsub1 = folium.plugins.FeatureGroupSubGroup(mc, name='- markers subcluster',
show=True,
control=False) # checkmark actually not shown
mcsub1.add_to(dmap)
# the layercontrol itself
lc = folium.map.LayerControl(collapsed=False)
lc.add_to(dmap)
# add geo markers
for _, data in df.iterrows():
mrk = segmrk(data['geo'], data['geo_path'])
mrk.add_to(mcsub1)
# this AntPath should be shown when popup appears OR when hovering marker
AntPath(data['geo_path']).add_to(dmap)
# show map
dmap
If you don't have too many markers, you can try this.
# imports
import pandas as pd
import folium
from folium.plugins import HeatMap
from folium.map import Marker, Template
# sample data
df = pd.DataFrame()
df['geo'] = [[52.5172, 12.1024],[52.5172, 12.2024],[52.5172, 12.3024]]
df['geo_path'] = [[[52.5172, 12.1024],[52.6172, 12.1024],[52.7172, 12.1024],[52.7172, 12.1024]],
[[52.5172, 12.2024],[52.6172, 12.2024],[52.7172, 12.2024],[52.7172, 12.2024]],
[[52.5172, 12.3024],[52.6172, 12.3024],[52.7172, 12.3024],[52.7172, 12.3024]],
]
# define map
geo_start = [52.5172, 12.2024]
dmap = folium.Map(location=geo_start,
zoom_start=10,
tiles='OpenStreetMap'
)
mapstyle_2 = folium.raster_layers.TileLayer(tiles='CartoDB dark_matter',
name='dark',
overlay=False,
control=True,
show=True,
)
mapstyle_2.add_to(dmap)
# add full screen button
folium.plugins.Fullscreen().add_to(dmap)
# Modify Marker template to include the onClick event
click_template = """{% macro script(this, kwargs) %}
var {{ this.get_name() }} = L.marker(
{{ this.location|tojson }},
{{ this.options|tojson }}
).addTo({{ this._parent.get_name() }}).on('click', onClick);
{% endmacro %}"""
# Change template to custom template
Marker._template = Template(click_template)
# add layercontrol
# markergroups in layercontrol
mc = folium.plugins.MarkerCluster(name='Segment Markers',
overlay=True,
control=True,
show=True,
disableClusteringAtZoom=10
)
mc.add_to(dmap)
mcsub1 = folium.plugins.FeatureGroupSubGroup(mc, name='- markers subcluster',
show=True,
control=False) # checkmark actually not shown
mcsub1.add_to(dmap)
# the layercontrol itself
lc = folium.map.LayerControl(collapsed=False)
lc.add_to(dmap)
# Create the onClick listener function as a branca element and add to the map html
map_id = dmap.get_name()
click_js = f"""function onClick(e) {{
var coords = e.target.options.pathCoords;
//var coords = JSON.stringify(coords);
//alert(coords);
var ant_path = L.polyline.antPath(coords, {{
"delay": 400,
"dashArray": [
10,
20
],
"weight": 5,
"color": "#0000FF",
"pulseColor": "#FFFFFF",
"paused": false,
"reverse": false,
"hardwareAccelerated": true
}});
{map_id}.eachLayer(function(layer){{
if (layer instanceof L.Polyline)
{{ {map_id}.removeLayer(layer) }}
}});
ant_path.addTo({map_id});
}}"""
e = folium.Element(click_js)
html = dmap.get_root()
html.script.add_child(e)
# add geo markers
for index, data in df.iterrows():
mrk = folium.Marker(data['geo'], pathCoords=data['geo_path'])
mrk.add_to(mcsub1)
# Add leaflet antpath plugin cdn link
link = folium.JavascriptLink("https://cdn.jsdelivr.net/npm/leaflet-ant-path@1.3.0/dist/leaflet-ant-path.js")
dmap.get_root().html.add_child(link)
# show map
dmap