Leafmap Legend Not displaying in shiny python
micboat opened this issue · 12 comments
Hi, thanks for an amazing package. its very easy to use. Not sure if this is something you can help with:
Environment Information
- leafmap version:0.35.2
- shiny:0.10.2
- shinywidgets:0.3.2
- Python version: 3.10.4
- Operating System: MacOS
mapclassify==2.6.1
ipywidgets==7.8.1
Description
Describe what you were trying to get done.
Am trying to render leafmap within shiny app (python) using the chloropleth example here:
example
What I Did
from ipyleaflet import *
from shiny.express import ui
from shinywidgets import render_widget
import leafmap
import geopandas as gpd
data = leafmap.examples.datasets.countries_geojson
ui.page_opts(title="Market Change Profile",
)
with ui.sidebar(open="open"):
ui.h4("Year Filter")
ui.nav_spacer()
with ui.nav_panel("Map"):
with ui.card(full_screen=True):
ui.card_header(f"Test Map")
@render_widget
def map_ui():
m = leafmap.Map()
m.add_data(
data, column="POP_EST", scheme="Quantiles", cmap="Blues", legend_title="Population"
)
return m
If there was a crash, please include the traceback here.
HTML(value="<html>\n<body>\n <div class='my-legend'>\n <div class='legend-title'>Population</div>\n <div class='legend-scale'>\n <ul class='legend-labels'>\n <li><span style='background:#f7fbff;'></span>[ 140, 2484780]</li>\n <li><span style='background:#c6dbef;'></span>( 2484780, 6229794]</li>\n <li><span style='background:#6baed6;'></span>( 6229794, 14668522]</li>\n <li><span style='background:#2171b5;'></span>( 14668522, 38476269]</li>\n <li><span style='background:#08306b;'></span>( 38476269, 1379302771]</li>\n </ul>\n </div>\n </div>\n\n <style type='text/css'>\n .my-legend .legend-title {\n text-align: left;\n margin-bottom: 2px;\n margin-left: 2px;\n font-weight: bold;\n font-size: 90%;\n }\n .my-legend .legend-scale ul {\n margin: 0;\n margin-bottom: 5px;\n padding: 0;\n float: left;\n list-style: none;\n }\n .my-legend .legend-scale ul li {\n font-size: 80%;\n list-style: none;\n margin-left: 1px;\n line-height: 18px;\n margin-bottom: 2px;\n }\n .my-legend ul.legend-labels li span {\n display: block;\n float: left;\n height: 16px;\n width: 30px;\n margin-right: 5px;\n margin-left: 2px;\n border: 1px solid #999;\n }\n .my-legend .legend-source {\n font-size: 70%;\n color: #999;\n clear: both;\n }\n .my-legend a {\n color: #777;\n }\n </style>\n</body>\n</html>\n")
INFO: 127.0.0.1:57549 - "GET /jupyter-leaflet.js HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:57545 - "GET /ipyevents.js HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:57547 - "GET /jupyter-leaflet.js HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:57549 - "GET /ipyevents.js HTTP/1.1" 404 Not Found
Sorry, I am not a shiny user. Does not map show up? Or just the legend does not show up?
I cant share the screenshot somehow but just the legend, map is ok INFO: 127.0.0.1:57549 - "GET /jupyter-leaflet.js HTTP/1.1" 404 Not Found INFO: 127.0.0.1:57545 - "GET /ipyevents.js HTTP/1.1" 404 Not Found INFO: 127.0.0.1:57547 - "GET /jupyter-leaflet.js HTTP/1.1" 404 Not Found INFO: 127.0.0.1:57549 - "GET /ipyevents.js HTTP/1.1" 404 Not Found
The legend is an ipywidget HTML widget. Can you try if shiny can display an HTML widget without leafmap?
https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html#html
widgets.HTML(
value="Hello <b>World</b>",
placeholder='Some HTML',
description='Some HTML',
)
Yes widgets work ok, this code displays the text as specified. Also the code commented out show an interactive widget:
from shiny.express import ui
from shinywidgets import render_widget
import ipywidgets as widgets
import leafmap
import geopandas as gpd
#data = leafmap.examples.datasets.countries_geojson
data = gpd.read_file('/Users/boatenmi/Downloads/countries.geojson')
ui.page_opts(title="Market Change Profile",
)
with ui.sidebar(open="open"):
ui.h4("Year Filter")
ui.nav_spacer()
with ui.nav_panel("Map"):
with ui.card(full_screen=True):
ui.card_header(f"Test Map")
@render_widget
def map_ui():
m = leafmap.Map()
m.add_data(
data, column="POP_EST", scheme="Quantiles", cmap="Blues", legend_title="Population"
)
return m
with ui.nav_panel("Widget"):
with ui.card(full_screen=True):
ui.card_header(f"TestWidget")
@render_widget
def widgets_ui():
k= widgets.HTML(
value="Hello <b>World</b>",
placeholder='Some HTML',
description='Some HTML',
)
# k= widgets.IntSlider(
# value=7,
# min=0,
# max=10,
# step=1,
# description='Test:',
# disabled=False,
# continuous_update=False,
# orientation='horizontal',
# readout=True,
# readout_format='d'
# )
return k```
How about this HTML? This is the template used by the legend.
https://github.com/opengeos/leafmap/blob/master/leafmap/data/template/legend.html
Yes that works as well. It generates a legend with the colors and corresponding values
Then the issue is probably related to the ipywidget Output widget. The legend widget is an Output widget, which displays the HTML widget. I guess shiny does not render the Output widget properly
https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html
Thanks. I will try to ask the question on the shiny platform. I think the newer versions of this package doesnt work at all, so there may be some major compactibility issues. I cant use ipywidgets >= version 8.
Yeah. I guess this is an upstream issue, either ipywidgets or shiny.
Interesting because if I use ipyleaflet directly, it works. like this:
from ipyleaflet import *
from shiny.express import ui
from shinywidgets import render_widget
import ipywidgets as widgets
from ipyleaflet import Map, LegendControl
import leafmap
#import leafmap.foliumap as leafmap
import geopandas as gpd
#data = leafmap.examples.datasets.countries_geojson
ui.page_opts(title="Market Change Profile",
)
with ui.sidebar(open="open"):
ui.h4("Year Filter")
ui.nav_spacer()
with ui.nav_panel("Map"):
with ui.card(full_screen=True):
ui.card_header(f"Test Map")
@render_widget
def map_ui():
mymap = Map(center=(-10, -45), zoom=4)
a_legend = LegendControl(
{"low": "#FAA", "medium": "#A55", "High": "#500"},
title="Legend",
position="bottomright")
mymap.add(a_legend)
return mymap
``` Wondering if the legend can be added manully to the map generated from leafmap
It is different. Leafmap does not use ipyleaflet's built-in LegendControl. It is a custom widget: an ipywidget Output widget with an HMTL widget displayed in it. If shiny can't render the Output widget, then it will not work.
Closing this issue for now as it has been reported upstream.