jupyter-widgets / ipyleaflet

A Jupyter - Leaflet.js bridge
https://ipyleaflet.readthedocs.io
MIT License
1.48k stars 363 forks source link

4 Questions about LayersControl and LayerGroup with ipyleaflet #1100

Open Nirdual opened 1 year ago

Nirdual commented 1 year ago

Hello pythoneers, I am developping an ipyleaflet app using jupyter notebook and i encountered the following issues. The script of an easy example is available below.

The 2 first points are easily managed with Folium in Python but i need the widgets and therefore i have to stick to ipyleaflet.

1) How to remove map from LayersControl ? I manage to move it from base layer to overlay layer by setting explicitely the 'layers' option in Map(). I am going to display the map anyway, i do not want it to be in the controls at all.

in folium : tile_layer = folium.TileLayer(control = False)

2) How to hide a layer by default at map loading (untick Points layer by default for example) ?

in folium : folium.FeatureGroup(name = "Points", control = True, show = False)

3) Why my Popups in group_labels do not show on the map ? This looks like issue #37, but only for Popup(). Popup() works properly when adding them 1 by 1 to the map. The issue seems to be related to the LayerGroup.

4) Is it possible to put widgets in LayersControl ? i wish to be able to show/hide legend, scale, mouse coordinates and further widgets i planned to add.

Bonus from R 1) I am looking for a widget that would be a merge of Combobox and SelectMultiple, something like in R shiny : shinyWidgets::pickerInput(inputId = "back_end_id", label = "Label", choices = list_of_choice, options = list(actions-box = TRUE, # add select all/deselect all button live-search = TRUE), # allow live type-searching multiple = TRUE) # allow multiple selection.

Bonus from R 2) Is there a way to create a full layer without a for loop, like in R : This takes a whole dataframe as input and creates all points in one shot. library(dplyr) library(leaflet) map <- leaflet %>%
setView(lng = 1.90, lat = 49.66, zoom = 12) %>% addProviderTiles("OpenStreetMap.France") %>% addCircleMarkers(data = mydata, lng = ~lon, lat = ~lat, color = "black", radius = 3, opacity = 1, label = ~name, popup = ~name, group = "Points")

Thanks in advance for your help.

from ipyleaflet import *
from ipywidgets import *
import pandas as pd

# Creating a simple dataframe for example purpose
df = pd.DataFrame({'name': ['A', 'B'],
                   'lat': [49.6588, 49.6651],
                   'lon': [1.9849, 1.9778],
                   'col': ['green', 'red']})

# Creating the map
carte = Map(center = (49.66, 1.98),
            controls = (FullScreenControl(), 
                        LayersControl(position = 'topright'),
                        ScaleControl(position = 'bottomleft', 
                                     imperial = False, 
                                     max_width = 80)),
            zoom = 11, min_zoom = 5, max_zoom = 17, zoom_control = False,
            double_click_zoom = False, scroll_wheel_zoom = True,
            layers = (basemap_to_tiles(basemaps.OpenStreetMap.France), ),
           )

group_points = LayerGroup(name = 'Points')
group_labels = LayerGroup(name = 'Labels')

for i in range(len(df)):

    group_points.add(
        CircleMarker(location = (df.lat[i], df.lon[i]), 
                     radius = 3, color = df.col[i],
                     name = df.name[i]
        )
    )

    group_labels.add(Popup(location = (df.lat[i], df.lon[i]),
                           child = HTML(df.name[i]),
                           close_button = False,
                           auto_close = False,
                           close_on_escape_key = False
                           )
                     )
    # For loop's end

# Adding groups to the map 
carte.add(group_points)
carte.add(group_labels)

# Adding mouse coordinates widget
coord = Label()

def handle_interaction(**kwargs):
    if kwargs.get('type') == 'mousemove':
        coord.value = str([round(x, 5) for x in kwargs.get('coordinates')])

carte.on_interaction(handle_interaction)

carte.add(WidgetControl(widget = coord, position = 'bottomleft'))
carte.add(LegendControl(position = 'bottomright',
                        legend = {'A' : '#00FF00',
                                  'B' : '#FF0000'}))

carte

map