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",
)
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.
import 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.org/{z}/{x}/{y}.png"},
{"label": "Stamen Terrain", "value": "https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.jpg"},
{"label": "Stamen Toner", "value": "https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png"},
{"label": "CartoDB Dark", "value": "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"},
],
value="https://{s}.tile.openstreetmap.org/{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)