def mk_map_region_selector(height='600px', **kwargs): from ipyleaflet import Map, WidgetControl, FullScreenControl, DrawControl from ipywidgets.widgets import Layout, Button, HTML from types import SimpleNamespace state = SimpleNamespace(selection=None, bounds=None, done=False) btn_done = Button(description='done', layout=Layout(width='5em')) btn_done.style.button_color = 'green' btn_done.disabled = True html_info = HTML( layout=Layout(flex='1 0 20em', width='20em', height='3em')) def update_info(txt): html_info.value = '<pre style="color:grey">' + txt + '</pre>' m = Map(**kwargs) if len(kwargs) else Map(zoom=2) m.scroll_wheel_zoom = True m.layout.height = height widgets = [ WidgetControl(widget=btn_done, position='topright'), WidgetControl(widget=html_info, position='bottomleft'), ] for w in widgets: m.add_control(w) draw = DrawControl() draw.circle = {} draw.polyline = {} draw.circlemarker = {} shape_opts = { "fillColor": "#fca45d", "color": "#000000", "fillOpacity": 0.1 } draw.rectangle = {"shapeOptions": shape_opts} poly_opts = {"shapeOptions": dict(**shape_opts)} poly_opts["shapeOptions"]["original"] = dict(**shape_opts) poly_opts["shapeOptions"]["editing"] = dict(**shape_opts) draw.polygon = poly_opts draw.edit = True draw.remove = True m.add_control(draw) m.add_control(FullScreenControl()) def on_done(btn): state.done = True btn_done.disabled = True m.remove_control(draw) for w in widgets: m.remove_control(w) def bounds_handler(event): (lat1, lon1), (lat2, lon2) = event['new'] txt = 'lat: [{:.{n}f}, {:.{n}f}]\nlon: [{:.{n}f}, {:.{n}f}]'.format( lat1, lat2, lon1, lon2, n=4) update_info(txt) state.bounds = dict(lat=(lat1, lat2), lon=(lon1, lon2)) def on_draw(event): v = event['new'] action = event['name'] if action == 'last_draw': state.selection = v['geometry'] elif action == 'last_action' and v == 'deleted': state.selection = None btn_done.disabled = state.selection is None draw.observe(on_draw) m.observe(bounds_handler, ('bounds', )) btn_done.on_click(on_done) return m, state
def mk_map_region_selector(map=None, height="600px", **kwargs): from ipyleaflet import Map, WidgetControl, FullScreenControl, DrawControl from ipywidgets.widgets import Layout, Button, HTML from types import SimpleNamespace state = SimpleNamespace(selection=None, bounds=None, done=False) btn_done = Button(description="done", layout=Layout(width="5em")) btn_done.style.button_color = "green" btn_done.disabled = True html_info = HTML(layout=Layout(flex="1 0 20em", width="20em", height="3em")) def update_info(txt): html_info.value = '<pre style="color:grey">' + txt + "</pre>" def render_bounds(bounds): (lat1, lon1), (lat2, lon2) = bounds txt = "lat: [{:.{n}f}, {:.{n}f}]\nlon: [{:.{n}f}, {:.{n}f}]".format( lat1, lat2, lon1, lon2, n=4 ) update_info(txt) if map is None: m = Map(**kwargs) if len(kwargs) else Map(zoom=2) m.scroll_wheel_zoom = True m.layout.height = height else: m = map render_bounds(m.bounds) widgets = [ WidgetControl(widget=btn_done, position="topright"), WidgetControl(widget=html_info, position="bottomleft"), ] for w in widgets: m.add_control(w) draw = DrawControl() draw.circle = {} draw.polyline = {} draw.circlemarker = {} shape_opts = {"fillColor": "#fca45d", "color": "#000000", "fillOpacity": 0.1} draw.rectangle = {"shapeOptions": shape_opts, "metric": ["km", "m"]} poly_opts = {"shapeOptions": dict(**shape_opts)} poly_opts["shapeOptions"]["original"] = dict(**shape_opts) poly_opts["shapeOptions"]["editing"] = dict(**shape_opts) draw.polygon = poly_opts draw.edit = True draw.remove = True m.add_control(draw) m.add_control(FullScreenControl()) def on_done(btn): state.done = True btn_done.disabled = True m.remove_control(draw) for w in widgets: m.remove_control(w) def bounds_handler(event): bounds = event["new"] render_bounds(bounds) (lat1, lon1), (lat2, lon2) = bounds state.bounds = dict(lat=(lat1, lat2), lon=(lon1, lon2)) def on_draw(event): v = event["new"] action = event["name"] if action == "last_draw": state.selection = v["geometry"] elif action == "last_action" and v == "deleted": state.selection = None btn_done.disabled = state.selection is None draw.observe(on_draw) m.observe(bounds_handler, ("bounds",)) btn_done.on_click(on_done) return m, state