9

I am writing a webapp where the user will click on the map and the latitude, longitude will be returned to the python script. the webapp is written on streamlit and for the map I am using folium. Currently, I used folium.LatLngPopup() to get the on click lat long of the clicked location, but I am very confused how to retrieve the values in my python script for further processing.

This is how it looks currently:

This is how it looks currently

#code snippet

import streamlit as st
from streamlit_folium import folium_static
import folium
m = folium.Map()
m.add_child(folium.LatLngPopup())
folium_static(m)

There might not be a native solution to it but any workaround will be appreciated!

tuntun
  • 91
  • 1
  • 5
  • What specific part are you confused about or having trouble with? – Axe319 Aug 14 '20 at 13:29
  • Passing those latitude longitude values from the pop-up to python variable. – tuntun Aug 14 '20 at 13:55
  • 1
    Currently, the package only displays a Folium map, it does not have bi-directional data transfer. If this is functionality you desire, I suggest opening an issue on the GitHub repository (I'm the package developer) – Randy Zwitch Aug 14 '20 at 14:00
  • Hey Randy, I used your package, thanks for having it there in the first place. I'll open an issue on github regarding it. But is there a way to deal with it for now, I tried a many ways but my lack of JS knowledge and folium's limitation on Js->python communication kinda held me implementing it. – tuntun Aug 14 '20 at 14:08
  • No, there isn't a way to deal with it at this moment. As I said, data only flows one-way currently, from Python to JavaScript. There are no return values. – Randy Zwitch Aug 14 '20 at 14:34

3 Answers3

4

If you can directly use the value instead of assigning it, you can just use map['last_clicked']['lat'] and map['last_clicked']['lng'] where map is defined. For example here I just print every location's lat/lng, but instead of just returning them, in a function you can do any operation you need:

import folium as fl
from streamlit_folium import st_folium
import streamlit as st

def get_pos(lat,lng):
    return lat,lng

m = fl.Map()

m.add_child(fl.LatLngPopup())

map = st_folium(m, height=350, width=700)


data = get_pos(map['last_clicked']['lat'],map['last_clicked']['lng'])

if data is not None:
    st.write(data)
  • 1
    Please provide working code with continuous lat/lng output, explain how you run this with the `streamlit` server, and how you exit. – not2qubit Aug 25 '22 at 01:22
  • Is it possible to feed the click event-data back into streamlit-folium? I was expecting to be able to e.g. center the map on the location of the mouse click, but I have not had any luck in getting the click data back into the map and have it react like I expected. – Lurifaxel Nov 07 '22 at 21:27
  • Answered your question not2qubit in new answer :) – a-doering Jun 29 '23 at 10:05
0

I recently encountered the same problem to get the latitude and longitude then print it or save the values to a variable. Apparently, I found out the usual streamlit is static as I tried to create a streamlit.button which is supposed to add 1 to variable counter if clicked. Result: the variable counter is printed as 1, regardless how many I clicked.

To be able to take the input, the streamlit component should be 'bi-directional'. I might not be able to explain it clearly as I am still newb both in python or in javascript, but in short it suppose to listen to the change in the values.

The solution is to create the bi-directional component and later I found this awesome repo streamlit-light-leaflet. To run it, just follow along the README.md. Assuming you already install streamlit in the virtual env, do the npm install and npm run start. Then run the 'streamlit run file.py' in different terminal/command line. Click the url from the terminal where you run the streamlit.

If the map doesn't show, go to my_component/frontend/src/index.tsx and put your mapbox.com accessToken. To get the accessToken, you should sign up first to mapbox.com. It would be best practice to use .env and call your mapbox accessToken from there, to keep the code cleaner.

Dharman
  • 30,962
  • 25
  • 85
  • 135
nggih
  • 21
  • 3
0

Building on the answer of francesco morri, I added the missing parts to make it run that address the questions under it. Super grateful about francescos answer.

# my_app.py
import folium as fl
from streamlit_folium import st_folium
import streamlit as st


def get_pos(lat, lng):
    return lat, lng


m = fl.Map()

m.add_child(fl.LatLngPopup())

map = st_folium(m, height=350, width=700)

data = None
if map.get("last_clicked"):
    data = get_pos(map["last_clicked"]["lat"], map["last_clicked"]["lng"])

if data is not None:
    st.write(data) # Writes to the app
    print(data) # Writes to terminal

Run it with:

streamlit run my_app.py
a-doering
  • 1,149
  • 10
  • 21