Hello everybody . I m new here
I have the problem of the topic and i cant resolve it
I m looking for a code that is able to do the job .
im using python 3.10 and dash
in a first approach
I want to click on a map everywhere of the europe.
I want to get the coordinates lon lat in a callback
And i want to place something in the map to say that this point is selected
I want to have the coordinates that are displayed
All the previous examples are complex or doesnt work for me
I dont understand . Dash plotly can do so magic things . And this simple task is a wall for me
I m on it for a while. Maybe the problem is between the screen of my computer and my chair.
Please someone has a code example who works ?
Angelo
hey @Angelo28300 welcome to the forums.
What did you try so far? Could you provide sample code?
EDIT, and example:
from dash import Dash, html, Input, Output, Patch
import dash_leaflet as dl
import json
app = Dash()
app.layout = html.Div(
[
dl.Map(
id='map',
children=[
dl.TileLayer()
],
center=[56, 10],
zoom=6,
style={'height': '50vh'}
),
html.Div(id='out')
]
)
@app.callback(
Output('out', 'children'),
Output('map', 'children'),
Input('map', 'clickData'),
prevent_initial_call=True
)
def do(click_data):
# extract coordinates form click_data
coordinates = click_data['latlng']
lat, lon = coordinates.values()
# create Patch() instance, add Marker layer at click coordinates
patched = Patch()
patched.append(dl.Marker(position=[lat, lon]))
return json.dumps(coordinates), patched
if __name__ == '__main__':
app.run(debug=True)
I tried the proposed code and it works partially fine .
I didn’t know the use of the Patch object .
The proposed code add a point on the map at each click . I would like that it was replaced by the new point at each click and the old disappear of the map
But it is the first time i have a begining of solution.
Thanks a lot AIMPED
You’re welcome @Angelo28300. You don’t necessarily have to use the Patch()
(partial updates), it decreases the data going from server to client.
An other example:
from dash import Dash, html, Input, Output
import dash_leaflet as dl
import json
app = Dash()
app.layout = html.Div(
[
dl.Map(
id='map',
children=[
dl.TileLayer()
],
center=[56, 10],
zoom=6,
style={'height': '50vh'}
),
html.Div(id='out')
]
)
@app.callback(
Output('out', 'children'),
Output('map', 'children'),
Input('map', 'clickData'),
prevent_initial_call=True
)
def do(click_data):
# extract coordinates form click_data
coordinates = click_data['latlng']
lat, lon = coordinates.values()
return json.dumps(coordinates), [dl.TileLayer(), dl.Marker(position=[lat, lon])]
if __name__ == '__main__':
app.run(debug=True)
If you need further assistance, let us know.
Wonderful. It’s really what i need . Thanks a lot. Is it possible to set a limit to the map?, for example , i want that the user can not select a point out of a box that is centered on europa.
Sure, you could do this. I would actually check, if the clicked point is within the boundaries of a geojson file (in your case, one of Europe).
from dash import Dash, html, Input, Output, Patch
import dash_leaflet as dl
import json
from shapely.geometry import shape, Point
with open('assets/europe.geojson', 'r') as f:
js = json.load(f)
def is_point_in(lat, lon, geojson=js):
point_in = False
# create shapely point
point = Point(lat, lon)
# check each feature in geojson, if point is within bounds
for feature in geojson['features']:
# create shapely shape from geojson feature
polygon = shape(feature['geometry'])
if polygon.contains(point):
point_in = True
break
return point_in
app = Dash()
app.layout = html.Div(
[
dl.Map(
id='map',
children=[
dl.TileLayer(),
# dl.GeoJSON(
# url='assets/europe.geojson'
# )
# ^^ comment in if you want to show the outline on map
],
center=[49, 10],
zoom=4,
style={'height': '50vh'}
),
html.Div(id='out')
]
)
@app.callback(
Output('out', 'children'),
Output('map', 'children'),
Input('map', 'clickData'),
prevent_initial_call=True
)
def do(click_data):
# extract coordinates form click_data
coordinates = click_data['latlng']
lat, lon = coordinates.values()
# check if clicked point is within Europe bounds
point_in_europe = is_point_in(lon, lat)
# Patch() instance
patched = Patch()
if point_in_europe:
# patched[2] = dl.Marker(position=[lat, lon])
# ^^ use this line if you are showing the geojson layer with european outline
patched[1] = dl.Marker(position=[lat, lon])
return json.dumps(coordinates), patched
if __name__ == '__main__':
app.run(debug=True)
For my tests I used this geojson file.
Woah . I tested it. It runs very well . Thanks a lot AIMPED .
testing the europa outlining , i see that If i click on the map one time the outlines disappears and the point appears . After that, the outlines dont come anymore , i need to reload the webpage to get it again .
Is it possible to preserve the outlining when one point is selected
Angelo
Just change
patched[1] = dl.Marker(position=[lat, lon])
To
patched[2] = dl.Marker(position=[lat, lon])
Thanks a lot . I understood my mistake.
It works really fine
Angelo
Yall might find this useful: https://geojson-maps.kyd.au/