Py.Cafe

lopezv.oliver/

solara-ipyleaflet-layer-sorting

Interactive Layer Mapping with Solara and ipyleaflet

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import ipyleaflet 
import solara  
from solara.widgets import GridLayout


@solara.component
def LayersControlMockup(
        title = 'Layers control',
        grid_layout:solara.reactive = None,
    ):

    with solara.Card(title = title):
        layer_names = [d['name'] for d in grid_layout.value]
        items = [solara.Text(f"{name}") for name in layer_names]

        def handle_grid_change(value):
            grid_layout.set(value)
        
        GridLayout.element(
            items=items, 
            grid_layout=grid_layout.value, 
            resizable=False, 
            draggable=True, 
            #on_grid_layout=handle_grid_change,    # πŸ‘ˆ Will trigger as soon as the layout changes
            on_layout_updated=handle_grid_change,  # πŸ‘ˆ Will trigger *only* when you release it
            col_num = 1  # Pending solara PR #1044
        )
        with solara.Card():
            solara.Markdown(
            """
            Drag the layer names above
            
            The layer on top is the layer that you see on the map
            
            Use `on_grid_layout` to see the changes while you are dragging the layers

            Use `on_layout_updated` to see the change only when you stop dragging the layer
            """)
            

# 3 Static XYZ layers to re-order:
initial_layer_defs = {
    'osm': dict(url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"),
    'aster': dict(url="https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/ASTER_GDEM_Greyscale_Shaded_Relief/default/GoogleMapsCompatible_Level12/{z}/{y}/{x}.jpg"),
    'esri': dict(url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer/tile/{z}/{y}/{x}")
}

grid_layout = solara.reactive([
    dict(i=0,h=1,w=12,x=0,y=0, name='esri'),   # change w=12 to w=1 when PR #1044 is merged
    dict(i=1,h=1,w=12,x=0,y=1, name='aster'),  # For now, `col_num` is not yet implemented 
    dict(i=2,h=1,w=12,x=0,y=2, name='osm'),    # (defaults to 12 columns).
])

meta_layer_defs = solara.reactive(initial_layer_defs)

@solara.component
def Page():
    def get_layers_to_add():
        print(grid_layout.value)
        layer_names = [d['name'] for d in sorted(grid_layout.value, key=lambda d: d["y"], reverse=True)]
        return {key: meta_layer_defs.value[key] 
                     for key in layer_names}

    layers_to_add = solara.use_memo(
        lambda: get_layers_to_add(),
        dependencies=[grid_layout.value]
    )
    layers = [
        ipyleaflet.TileLayer.element(
            url = layer['url'].value if hasattr(layer['url'],'value') else layer['url'],
        )
        for _,layer in layers_to_add.items()
    ]

    with solara.Columns([1,1]):

        LayersControlMockup(
                grid_layout=grid_layout
            )

        
        with solara.Column(style={"isolation": "isolate"}):
            ipyleaflet.Map.element(
                dragging = False, # only for this notebook
                layers = layers,
                zoom = 5,        # constant for this notebook
                center=(30,38),   # constant for this notebook
                controls = []
            )


Page()