Hello all,
I am aiming to create a simple, interactive editor of geometric features within the context of a map, and I am looking at various options for doing so. I only need to edit linestrings (polylines) and points. This will be based on GeoJSON objects.
I am currently looking at Dash Leaflet, which looks (to me) to be the most promising solution for my need. I have also looked at other solutions. A precursor regarding myself is that I am not familiar with the use of Leaflet natively, so I am on a learning curve both with regards to Dash Leaflet and Leaflet itself.
So - I think I can figure out how to interactively edit (i.e. move) a point that has been declared explicitly. But I canāt figure out how to interactively edit a polyline which has come into Dash Leaflet as a GeoJSON object by file. I havenāt tried points coming from a GeoJSON yet. I have tried a rather naive example based on an example on the Dash Leaflet Documentation Site, and whilst this small app is doing partly what I want it to do, it does not allow me to edit points of that polyline. What I wanted to achieve with the example attached was to:
- allow for creation of new features from scratch using the editor. I have that one under control through Emilās example - at least I believe so.
- āpromoteā existing features imported from a GeoJSON object to be edited by ā deleting it from the GeoJSON object and then putting it into the editControl variable.
- allow for dragging and dropping of every point along that polyline.
I did not get that far - I can append to the editable version, but I canāt edit. Anyone who can point me in the right direction? The attached example is for illustration purposes only - I may well be barking up the wrong tree.
Best regards,
KjetilF
Code for illustration purposes:
import geojson
import dash_html_components as html
import dash_leaflet as dl
from dash import Dash
from dash.dependencies import Output, Input, State
from dash_extensions.javascript import assign
from dash.exceptions import PreventUpdate
from dash_extensions.javascript import arrow_function
How to render geojson.
point_to_layer = assign(""āfunction(feature, latlng, context){
const p = feature.properties;
if(p.type === ācirclemarkerā){return L.circleMarker(latlng, radius=p._radius)}
if(p.type === ācircleā){return L.circle(latlng, radius=p._mRadius)}
return L.marker(latlng);
}ā"")
filename = āā¦/data/builder/TwoLineStringFeatures.geojsonā
with open(filename) as json_file:
cableNetwork = geojson.load(json_file)
print(cableNetwork)
cables_in_map = dl.GeoJSON(data=cableNetwork,
zoomToBounds=True,
zoomToBoundsOnClick=True,
options=dict(color=āredā, pointToLayer=point_to_layer),
hoverStyle=arrow_function(dict(weight=5, color=ā#666ā, dashArray=āā)),
id=ābuilder-cables-in-mapā
)
app = Dash()
app.layout = html.Div([
# Setup a map with the edit control.
dl.Map(center=[58, 10.2], zoom=4, children=[
dl.TileLayer(), dl.FeatureGroup([
dl.EditControl(id=āedit_controlā), cables_in_map, dl.Marker(id=āmarkerā, position=[59.9
, 10.5], draggable=True)]),
], style={āwidthā: ā50%ā, āheightā: ā50vhā, āmarginā: āautoā, ādisplayā: āinline-blockā}, id=āmapā),
# Setup another map to that mirrors the edit control geometries using the GeoJSON component.
dl.Map(center=[56, 10], zoom=4, children=[
dl.TileLayer(), dl.GeoJSON(id=āgeojsonā, options=dict(pointToLayer=point_to_layer), zoomToBounds=True),
], style={āwidthā: ā50%ā, āheightā: ā50vhā, āmarginā: āautoā, ādisplayā: āinline-blockā}, id=āmirrorā),
])
@app.callback(Output(component_id=āgeojsonā, component_property=ādataā),
Input(component_id=āedit_controlā, component_property=āgeojsonā))
def mirror(x):
if not x:
raise PreventUpdate
print(x)
return x
@app.callback(Output(component_id=ābuilder-cables-in-mapā, component_property=ādataā),
Output(component_id=āedit_controlā, component_property=āgeojsonā),
Input(component_id=ābuilder-cables-in-mapā, component_property=āclick_featureā),
State(component_id=ābuilder-cables-in-mapā, component_property=ādataā),
State(component_id=āedit_controlā, component_property=āgeojsonā),
prevent_initial_call=True)
def update_map_view(clickFeature, cablesInMap, editControl):
if clickFeature is not None and editControl is not None:
editControl[āfeaturesā].append(clickFeature)
cablesInMap[āfeaturesā].remove(clickFeature)
return cablesInMap, editControl
if name == āmainā:
app.run_server()