jupyter-widgets / ipyleaflet

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

Draw control can't stop drawing after draw more than one shape #1119

Open J-Bindel opened 1 year ago

J-Bindel commented 1 year ago

Hey,

I am using ipyleaflet for my work. I would like to draw rectangles on my map with DrawControl.

from ipyleaflet import Map, DrawControl

map = Map(center=(49.115469, -1.082814), zoom=10)
dc = DrawControl(
    marker={"shapeOptions": {"color": "#0000FF"}},
    rectangle={"shapeOptions": {"color": "#0000FF"}},
    circle={"shapeOptions": {"color": "#0000FF"}},
    circlemarker={},
)
map.add(dc)
display(map)

The first drawing works but when I click again on the rectangle for example, DrawControl won't stop drawing rectangles until I clear them all.

The above code reproduces the bug.

Here is what I get. Screencast from 19-06-2023 18:39:08.webm

cr458 commented 1 year ago

+1 also might be somewhat related: I can't draw more than one polygon, the second polygon I try to draw never closes. Similar to. @J-Bindel what version of python and ipyleaflet are you using?

J-Bindel commented 1 year ago

I am using:

mangecoeur commented 12 months ago

I see something similar, the draw menu stays open and you have to click save then cancel and it seems to work but its janky.

Checking the javascript console I see the error:

Error serializing widget state attribute:  data [widget.js:492:24](webpack://widgetti/solara-widget-manager8/node_modules/@jupyter-widgets/base/lib/widget.js)
    serialize widget.js:492
    sync widget.js:416
    save Backbone
    save_changes widget.js:549
    layers_to_data DrawControl.js:148
    create_obj DrawControl.js:95
    fire leaflet-src.js:613
    _fireCreatedEvent leaflet.draw.js:8
    _fireCreatedEvent leaflet.draw.js:8
    completeShape leaflet.draw.js:8
    s leaflet-src.js:2692
    (Async: EventListener.handleEvent)
    Te leaflet-src.js:2719
    ke leaflet-src.js:2618
    _createButton leaflet.draw.js:9
    _createActions leaflet.draw.js:9
    _showActionsToolbar leaflet.draw.js:9
    _handlerActivated leaflet.draw.js:9
    fire leaflet-src.js:613
    enable leaflet.draw.js:8
    s leaflet-src.js:2692

My unconfirmed hunch digging into the code is that line 39 in DrawControl.js

    this.feature_group = L.geoJson([], {
      style: function (feature) {
        return feature.properties.style;
      },

is setting a property as a function which fails to be synced by the widget.

mangecoeur commented 12 months ago

also possibly related https://github.com/jupyter-widgets/ipywidgets/issues/3735

sufyanAbbasi commented 11 months ago

I can reproduce your findings by running ipyleaflet in Jupyer-Lab, editing a polygon and hitting save. This does nothing and the console (with breakpoints) shows the following errors:

Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': function(e){return e.properties.style} could not be cloned.

Which is caught and logged:

Error serializing widget state attribute:  data

resulting in the data attribute not being reflected of the geometries on the JS layer.

This can be traced to the ipywidget serialization logic here: https://github.com/jupyter-widgets/ipywidgets/blob/e1718c2b3bf0b143580ef87f71c55fbc6ed50a77/packages/base/src/widget.ts#L587

which is corroborated by the above discussion about moving away from structuredClone.

Can we clean up newData before we set it on the model?

https://github.com/jupyter-widgets/ipyleaflet/blob/ddeab67de9dff00df8a14ebb37216277e026d063/js/src/controls/DrawControl.js#L147C5-L147C37

joHussien commented 3 months ago

@J-Bindel Did you find a solution to this problem?

J-Bindel commented 3 months ago

No, sorry 😔

mangecoeur commented 3 months ago

The JS library behind the draw control is not maintained so there is a new PR to use geoman instead, which should hopefully also fix this issue On 3 Apr 2024, at 21:04, Jeremy Bindel @.***> wrote: No, sorry 😔

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>