Combination Streamlit and Folium in VS-code
I try to create the code using Streamlit and Folium(Steamlit_Folium) and to learn about publicizing the code on the WEB site of the Streamlit.
I think what kind of Application I will make. I decided to make a code like below.
- input the latitude and longitude at a point and a radius in our side bar
- Draw the circle that has an inputed coordinate and the center
I ask Gemini like below, in Japanese.
Streamlitを使って、入力した緯度・経度の点とその点を中心とする半径から、Foliumの地図上に当該緯度経度の点をドットで表示したうえで、当該点を中心とする半径の円を描くPythonコードを書いてください。なお、緯度経度と半径の入力はサイドバーを使用したいです。
StreamlitとFoliumを組み合わせることで、サイドバーからインタラクティブに数値を変更し、地図上に反映させるアプリケーションを簡単に作成できます。
以下のコードは、streamlit-folium というライブラリを使用して、Streamlit上にFoliumの地図を表示する実装例です。
実装コード
import streamlit as st
import folium
from streamlit_folium import st_folium
# ページの設定
st.set_page_config(page_title="Map Circle Tool", layout="wide")
st.title("📍 緯度経度を中心とした円の描画")
# --- サイドバーの設定 ---
st.sidebar.header("入力パラメータ")
# 緯度の入力(デフォルト:東京駅)
lat = st.sidebar.number_input(
"緯度 (Latitude)",
min_value=-90.0, max_value=90.0, value=35.6812, format="%.6f"
)
# 経度の入力
lon = st.sidebar.number_input(
"経度 (Longitude)",
min_value=-180.0, max_value=180.0, value=139.7671, format="%.6f"
)
# 半径の入力(メートル単位)
radius = st.sidebar.number_input(
"半径 (メートル)",
min_value=1, max_value=100000, value=1000, step=100
)
# --- 地図の作成 ---
# 地図の初期化(入力された地点を中心に設定)
m = folium.Map(location=[lat, lon], zoom_start=14)
# 中心点にドット(CircleMarker)を配置
folium.CircleMarker(
location=[lat, lon],
radius=5, # ドットの大きさ
color="red",
fill=True,
fill_color="red",
tooltip="中心点"
).add_to(m)
# 指定された半径の円を配置
folium.Circle(
location=[lat, lon],
radius=radius, # メートル単位
color="blue",
fill=True,
fill_opacity=0.2,
tooltip=f"半径 {radius}m"
).add_to(m)
# --- Streamlitでの表示 ---
st_folium(m, width=1000, height=600, returned_objects=[])
# 現在の値を表示
st.write(f"現在の設定: 緯度 {lat}, 経度 {lon}, 半径 {radius}m")
実行方法
ライブラリのインストール
まだインストールしていない場合は、ターミナルで以下を実行してください。
Bashpip install streamlit folium streamlit-foliumアプリの起動
作成したPythonファイルを app.py として保存し、以下を実行します。
Bashstreamlit run app.py
コードのポイント
st.sidebar.number_input: 数値入力欄をサイドバーに配置します。format="%.6f"とすることで、GPS座標のような細かい小数点も扱えるようにしています。folium.CircleMarker: 地図をズームしても大きさが変わらない「ドット」を描画するのに適しています。folium.Circle: 地図上の実際の距離(メートル)に基づいた円を描画します。st_folium: FoliumのオブジェクトをStreamlit上で描画するためのコンポーネントです。
もし、この地図に「CSVファイルを読み込んで複数の点を一括表示したい」といった機能を追加したい場合は、続けてお手伝いしましょうか?
緯度経度と半径の入力は、Streamlitのnumber_input機能を使用したいです。なお、緯度経度の初期値は東京都庁の場所、半径は1kmを初期値にしてください
承知いたしました。東京都庁の座標(緯度: 35.6895, 経度: 139.6917)と半径 1,000m を初期値に設定し、st.sidebar.number_input を活用したコードを作成しました。
実装コード
import streamlit as st
import folium
from streamlit_folium import st_folium
# ページのレイアウト設定
st.set_page_config(page_title="都庁中心の円描画", layout="wide")
st.title("📍 緯度・経度指定による円の描画")
# --- サイドバーの設定 ---
st.sidebar.header("設定パラメータ")
# 1. 緯度の入力(初期値:東京都庁)
lat = st.sidebar.number_input(
"緯度 (Latitude)",
min_value=-90.0,
max_value=90.0,
value=35.689500,
format="%.6f"
)
# 2. 経度の入力(初期値:東京都庁)
lon = st.sidebar.number_input(
"経度 (Longitude)",
min_value=-180.0,
max_value=180.0,
value=139.691700,
format="%.6f"
)
# 3. 半径の入力(初期値:1000m = 1km)
radius = st.sidebar.number_input(
"半径 (メートル)",
min_value=1,
max_value=500000,
value=1000,
step=100
)
# --- Folium地図の作成 ---
# 指定した緯度経度を中心に表示
m = folium.Map(location=[lat, lon], zoom_start=14)
# 中心点のドット(CircleMarker)
folium.CircleMarker(
location=[lat, lon],
radius=6,
color="blue",
fill=True,
fill_color="blue",
tooltip="中心点"
).add_to(m)
# 指定半径の円(Circle)
folium.Circle(
location=[lat, lon],
radius=radius,
color="crimson",
fill=True,
fill_opacity=0.2,
tooltip=f"半径 {radius}m の範囲"
).add_to(m)
# --- 地図の表示 ---
st_folium(m, width=1000, height=600)
# 補足情報の表示
st.info(f"現在、東京都庁(付近)の座標を中心として、半径 {radius / 1000:.1f} km の円を描画しています。")
コードの解説
初期値の設定:
number_inputのvalue引数に、ご要望通りの値をセットしています。緯度:
35.689500経度:
139.691700半径:
1000
精度の確保:
format="%.6f"を指定することで、緯度経度のような細かい小数点以下(6桁)までサイドバー上で正確に表示・入力できるようにしています。視認性:
CircleMarker(ドット)とCircle(範囲)の色を変えて、中心位置がより分かりやすくなるようにしました。
この地図上に、半径に応じた「周辺の施設情報(コンビニや駅など)」を自動で検索して表示するような機能に興味はありますか?必要であればAPIとの連携方法などもご提案できます。
では、Streamlitで地図を表示して、地図上でクリックした場所の緯度経度を取得することはできますか?
はい、st_folium の戻り値を利用することで可能です。
st_folium 関数は、地図上でのクリックイベントや表示範囲の変更などの情報を Python の辞書(Dict)形式で返してくれます。クリックした場所の座標は、その辞書内の last_clicked というキーに格納されています。
以下に、クリックした場所の座標を取得し、それをサイドバーの入力値に反映(または表示)させる実装例を紹介します。
実装コード
import streamlit as st
import folium
from streamlit_folium import st_folium
st.set_page_config(layout="wide")
st.title("🖱️ 地図クリックで座標を取得")
# セッション状態(クリック座標を保存するため)の初期化
if 'clicked_lat' not in st.session_state:
st.session_state.clicked_lat = 35.6895
if 'clicked_lon' not in st.session_state:
st.session_state.clicked_lon = 139.6917
# --- サイドバーの設定 ---
st.sidebar.header("座標と半径の設定")
# サイドバーの入力(セッション状態を初期値に設定)
lat = st.sidebar.number_input("緯度", value=st.session_state.clicked_lat, format="%.6f")
lon = st.sidebar.number_input("経度", value=st.session_state.clicked_lon, format="%.6f")
radius = st.sidebar.number_input("半径 (m)", value=1000, step=100)
# --- 地図の作成 ---
m = folium.Map(location=[lat, lon], zoom_start=14)
# クリック地点にマーカーを表示
folium.Marker([lat, lon], tooltip="選択中の地点").add_to(m)
folium.Circle([lat, lon], radius=radius, color="red", fill=True).add_to(m)
# 地図を描画し、クリックイベントを取得
# returned_objects に "last_clicked" を指定することで情報を取得可能
map_data = st_folium(m, width=800, height=500)
# --- クリック時の処理 ---
if map_data and map_data["last_clicked"]:
new_lat = map_data["last_clicked"]["lat"]
new_lon = map_data["last_clicked"]["lng"]
# クリックされた座標が現在のセッションと異なる場合、更新してリラン
if new_lat != st.session_state.clicked_lat or new_lon != st.session_state.clicked_lon:
st.session_state.clicked_lat = new_lat
st.session_state.clicked_lon = new_lon
st.rerun()
st.write(f"現在の中心座標: {lat}, {lon}")
st.info("地図上をクリックすると、その地点に円が移動します。")
仕組みの解説
map_data["last_clicked"]:
st_folium を変数(上記では map_data)に代入すると、地図に対する操作ログがリアルタイムで格納されます。クリックすると {'lat': 35.xxx, 'lng': 139.xxx} というデータが取得できます。
st.session_state:
地図をクリックしてページが再読み込み(リラン)された際、クリックした座標を保持しておくために必要です。これがないと、クリックするたびに初期値(都庁)に戻ってしまいます。
st.rerun():
新しい座標を取得した瞬間にアプリを強制的に再描画させ、サイドバーの number_input や地図上の円を即座に更新するために使用します。
注意点
クリックしてから地図が更新されるまで、わずかに(コンマ数秒)通信のタイムラグが発生します。これは Streamlit がサーバーサイドで動作しているためです。
この「クリックで取得した座標」を使って、さらに**その場所の住所を自動表示(逆ジオコーディング)**するような機能を追加しましょうか?
I'd like to signify the center point select on the map, Gemini give the code like above.
Examplely, the center set Japanese Imperial Palace, the radius set 2_000m, the result is below
JR Iidabashi St., Yotsuya St., Shinbashi St. Tokyo St. and the others is within this circle.
Next, I try to publicize this code on the Streamlit. At first, I upload this code to GitHub.
At first, I log in the GitHub ( I have already registored to GitHub). After I log in the GitHub, I show this one like below.
For I should create a remort repogitory, I click the '+' button where is upper right side odf Header above windows. Next I input repository name as 'Streamlit_Test_Repository' and since this repository is for practice(test), I select 'Private' as publicity area.
Next I open 'Git Bush' like below.
Next, I try to set up 'Streamlit_Test_Repository' as my current remote repository. I input 'git remote add origin <URL>' , but an error happen like below.
$ git remote add origin
fatal: not a git repository (or any of the parent directories): .git
Maybe I need to move to the folder that be managed currently, then I input below command on the Git Bush.
$ cd "C:\Users\*****\OneDrive\ドキュメント\VS_Code\2025_StreamlitBasicLearning\2025_StreamlitAndFoliumLearn"
免責事項 本リポジトリのコードおよび情報は、教育的および学習目的でのみ提供されています。本プログラムの使用、適用、または実行によって生じたいかなる損害(データの損失、システムの不具合等)についても、作成者は一切の責任を負いません。すべて利用者の自己責任において使用してください。
英語 (English)
Disclaimer The code and information in this repository are provided for educational and learning purposes only. The author shall not be held liable for any damages (including but not limited to data loss or system failure) arising from the use, application, or execution of this program. Use it at your own risk.
Before I'll try to use Streamlit Cloud, Gemini is recommended that I should write in Streamlit sidebar like below.
import streamlit as st
with st.sidebar:
st.markdown("---")
st.caption("### Disclaimer / 免責事項")
st.caption("This app is for educational purposes. Use at your own risk.")
st.caption("本アプリは学習用です。利用による責任は負いかねます。")
I added this code to my repository's code, as the result like below.
Finally, I try to publicize on Streamllit Cloud. At first, I search Streamlit Cloud Home Page on the web site by Google. That is 'https://share.streamlit.io/' whose home page's windown is shown like below.
I click 'Create App' at upper right corner of window.
I selected 'Deploy a public app from GitHub' and write the necessary items like below.(Caution: If you'd like to create Web App from GitHub remote repository by Streamlit, the GitHub remote repository have to set up 'Public'.
I try to Deploy.
As the result, I have created Web App on Streamlit.I finish this time BLOG.
--ended
コメント
コメントを投稿