I'm slowly discovering the dash-leaflet
interface coming from ipyleaflet widget lib and there are still some tasks that I don't manage to achieve.
Here I would like to add a dash componenent (in this case a dropdown select) and place it on the map as control so it fits consistently with the leaflet layout when the map is resized.
Here is a map:
import dash_leaflet as dl
from dash import Dash
colorscale = ['red', 'yellow', 'green', 'blue', 'purple'] # rainbow
app = Dash()
app.layout = dl.Map(
[dl.TileLayer()],
center=[56, 10],
zoom=6,
style={'height': '100vh'},
)
if __name__ == "__main__":
app.run_server()
And here is the little select that I would like to place on it:
from dash import dcc
dropdown = dcc.Dropdown(
component_label="toto-label",
id="toto-id",
options=[
{"label": "NDVI (8)", "value": "ndvi8"},
{"label": "NDVI (16)", "value": "ndvi16"},
],
value="ndvi16",
)
EDIT
to clarify exactly what I'm looking for, I want to mimick what the WidgetControl
is doing in ipyleaflet i.e. placing the component in the controls hierarchy with something like "topleft" and without creating dedicated css styling.
I'm slowly discovering the dash-leaflet
interface coming from ipyleaflet widget lib and there are still some tasks that I don't manage to achieve.
Here I would like to add a dash componenent (in this case a dropdown select) and place it on the map as control so it fits consistently with the leaflet layout when the map is resized.
Here is a map:
import dash_leaflet as dl
from dash import Dash
colorscale = ['red', 'yellow', 'green', 'blue', 'purple'] # rainbow
app = Dash()
app.layout = dl.Map(
[dl.TileLayer()],
center=[56, 10],
zoom=6,
style={'height': '100vh'},
)
if __name__ == "__main__":
app.run_server()
And here is the little select that I would like to place on it:
from dash import dcc
dropdown = dcc.Dropdown(
component_label="toto-label",
id="toto-id",
options=[
{"label": "NDVI (8)", "value": "ndvi8"},
{"label": "NDVI (16)", "value": "ndvi16"},
],
value="ndvi16",
)
EDIT
to clarify exactly what I'm looking for, I want to mimick what the WidgetControl
is doing in ipyleaflet i.e. placing the component in the controls hierarchy with something like "topleft" and without creating dedicated css styling.
- Could you use different image for these dropdown {"label": "NDVI (8)", "value": "ndvi8"}, {"label": "NDVI (16)", "value": "ndvi16"},? – Subir Chowdhury Commented Apr 1 at 8:32
- Or could you provide url for each dropdown options? – Subir Chowdhury Commented Apr 1 at 8:41
- the dropdown is the smallest example I could think about for something much more complicated. In the real use case, I need to add a dropdown, a datepicker and a select that actually triggers the computation of the tile on the GEE servers on the fly. so no creating multiple images for each combination of my parameters is not an option. – Pierrick Rambaud Commented Apr 1 at 8:43
- Please review the updated code if it works for you. – Subir Chowdhury Commented Apr 1 at 8:47
1 Answer
Reset to default 2import dash
import dash_leaflet as dl
from dash import html, dcc, Output, Input
app = dash.Dash()
dropdown = dcc.Dropdown(
id="layer-dropdown",
options=[
{"label": "OpenStreetMap", "value": "https://{s}.tile.openstreetmap./{z}/{x}/{y}.png"},
{"label": "Stamen Terrain", "value": "https://stamen-tiles.a.ssl.fastly/terrain/{z}/{x}/{y}.jpg"},
{"label": "Stamen Toner", "value": "https://stamen-tiles.a.ssl.fastly/toner/{z}/{x}/{y}.png"},
{"label": "CartoDB Dark", "value": "https://{s}.basemaps.cartocdn/dark_all/{z}/{x}/{y}{r}.png"},
],
value="https://{s}.tile.openstreetmap./{z}/{x}/{y}.png",
style={"width": "200px"},
)
dropdown_control = html.Div(
dropdown,
style={
"position": "absolute",
"top": "10px", # Adjust this to move it lower or higher
"right": "10px", # Position it like a Leaflet control
"zIndex": "1000", # Ensure it appears above the map
"background": "white",
"padding": "5px",
"border-radius": "5px",
"box-shadow": "2px 2px 5px rgba(0,0,0,0.3)",
},
)
app.layout = html.Div(
[
html.Div(
[
dl.Map(
[
dl.TileLayer(id="base-layer", url=dropdown.value), # Dynamic Tile Layer
],
id="map",
center=[56, 10],
zoom=6,
style={"height": "100vh", "width": "100%"},
),
],
style={"position": "relative"},
),
dropdown_control, # Add the dropdown separately on top of the map
],
style={"position": "relative"},
)
@app.callback(
Output("base-layer", "url"), # Update the TileLayer URL
Input("layer-dropdown", "value"),
)
def update_map_layer(selected_layer):
return selected_layer
if __name__ == "__main__":
app.run(debug=True)