Py.Cafe

iisakkirotko/

project-2

Interactive Map Viewer - 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
from typing import Any, Union

import solara
import ipyleaflet
import ipywidgets

data: solara.Reactive[list[Any]] = solara.reactive([])

center_default = [53.2305799, 6.5323552]
zoom_default = 5.502

zoom = solara.reactive(zoom_default)
center = solara.reactive(center_default)

map_layer = ipyleaflet.basemaps.OpenStreetMap.Mapnik.build_url()
current_mode: solara.Reactive[Union[str, bool, None]] = solara.reactive(None)

@solara.component
def Page():
    def on_draw(obj, action, geo_json):
        if action == "create":
            data.value = [*data.value, *geo_json]
        elif action == "remove":
            data.value = [
                x
                for x in data.value
                if any(
                    x["geometry"]["coordinates"] != feature["geometry"]["coordinates"]
                    for feature in geo_json
                )
            ]
        else:  # All others are edit actions (inc. cut)
            data.value = geo_json

    draw_control = ipyleaflet.GeomanDrawControl.element(
        current_mode=current_mode.value,
        data=data.value,
        text={ 'pathOptions': {} },
        marker={ 'icon': {} },
    )

    def add_callback():
        widget = solara.get_widget(draw_control)
        widget.on_draw(on_draw)

        def cleanup():
            widget.on_draw(on_draw, remove=True)

        return cleanup

    solara.use_effect(add_callback, dependencies=None)
    
    with solara.Column(style={"height": "90%"}):
        with solara.Column(align="center"):
            with solara.ToggleButtonsSingle(value=current_mode, mandatory=False):
                solara.Button("Draw", value="draw:Polygon")
                solara.Button("Edit", value="edit")
                solara.Button("Delete", value="remove")
                solara.Button("cut", value="cut")

        with solara.Column(style={"flex-grow": "1"}):
            ipyleaflet.Map.element(  # type: ignore
                zoom=zoom.value,
                on_zoom=zoom.set,
                center=center.value,
                on_center=center.set,
                scroll_wheel_zoom=True,
                layers=[ipyleaflet.TileLayer.element(url=map_layer)],
                controls=[draw_control, ipyleaflet.ZoomControl.element()],
                layout=ipywidgets.Layout(height="100%"),
            )

        solara.Text(str(data.value))