Skip to content

Instantly share code, notes, and snippets.

@hansthen
Created June 18, 2025 21:12
Show Gist options
  • Save hansthen/74211c5aefd3b3781f5549f3c325a0da to your computer and use it in GitHub Desktop.
Save hansthen/74211c5aefd3b3781f5549f3c325a0da to your computer and use it in GitHub Desktop.
geoman multiple shapes
import folium
import streamlit as st
from folium.plugins import GeoMan, MousePosition
from folium import JsCode
from streamlit_folium import st_folium
st.set_page_config(
page_title="geoman",
layout="wide"
)
"""
# Folium: GeoMan plugin support
Folium support the GeoMan plugin
As with the Draw plugin, you can add a feature_group
to the plugin, which will initialize the plugin with
predefined shapes.
"""
with st.echo(code_location="below"):
left, right = st.columns([4,1])
with left:
items = folium.FeatureGroup()
#marker = folium.CircleMarker(location=[38, -83]).add_to(items)
m = folium.Map(location=[40.73, -73.94], zoom_start=12)
rt = folium.GeoJson(
"https://raw.githubusercontent.com/python-visualization/folium-example-data/main/subway_stations.geojson",
get_feature_id=JsCode("(f) => { return f.properties.objectid; }"),
point_to_layer=JsCode("""
(f, latlng) => {
return L.circleMarker(latlng, {
radius: 6,
color: "light gray",
fillOpacity: 0.7,
// No editing using geoman
pmIgnore: true,
})
}
"""),
style=JsCode("""
(f) => {
if (f.properties.ignore === undefined ||
f.properties.ignore === false) {
return {"color": "light gray"};
} else {
return {"color": "green"};
};
}
"""),
on_each_feature=JsCode("""
(f, layer) => {
layer.on("click", (event) => {
var loc = event.sourceTarget.feature.geometry;
var layer = event.sourceTarget;
if (f.properties.ignore === undefined ||
f.properties.ignore === false) {
f.properties.ignore = true;
layer.setStyle({"color": "green"});
} else {
f.properties.ignore = false;
layer.setStyle({"color": "light gray"});
};
// Return this to streamlit
var parents = layer._eventParents;
var geojson_layer = parents[Object.keys(parents)[0]];
var geojson = geojson_layer.toGeoJSON();
// Filter only ignored features
geojson.features = geojson.features.filter(
(f) => f.properties.ignore === true
);
// TODO: wrap this in an event
Streamlit.setComponentValue(geojson);
});
}
""")
)
rt.add_to(m)
items.add_to(m)
MousePosition().add_to(m)
handler = JsCode("""
(e) => {
var map = %(map)s;
var layers = L.PM.Utils.findLayers(map);
var lg = L.layerGroup(layers);
/* FIXME: we need to add a radius to circles */
Streamlit.setComponentValue(lg.toGeoJSON());
}
""" % dict(map=m.get_name())
)
click = JsCode("""
(e) => {
console.log(e.target);
console.log(e.target.toGeoJSON());
}
"""
)
gm = GeoMan(
feature_group=items,
draw_marker=False,
draw_polyline=False,
draw_circle_marker=False,
draw_text=False,
on={
"click": click
}
).add_to(m)
event_handlers = {
"pm:create": handler,
"pm:remove": handler,
"pm:update": handler,
"pm:rotateend": handler,
"pm:cut": handler,
"pm:undoremove": handler,
}
m.on(**event_handlers)
with st.expander("generated html"):
st.code(m.get_root().render())
8,1 Top
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment