Fletで世界の地震情報を表示してみた
はじめに
Fletでマップを表示できることを知り、地震情報の描画を試してみました。
Fletは、FlutterをベースにしたPythonフレームワークで、Web、デスクトップ、モバイルアプリケーションに対応しています。個人的には、ロゴがポップな感じで好きです。
動作環境
- WSL2 Ubuntu (Windows 11)
- Python 3.12.3
- uv 0.5.18
- flet 0.25.2
環境構築
uvを使用して、仮想環境でFletを使えるようにしました[1]。
# プロジェクトの作成
uv init flet-map
cd flet-map
# ライブラリの追加
uv add flet[all]
uv add requests
# Fletアプリケーションのテンプレート作成
uv run flet create .
上記を実行すると、ディレクトリ構造はこのようになります。
.
├── README.md
├── hello.py
├── pyproject.toml
├── src
│ ├── assets
│ │ └── icon.png
│ └── main.py
├── storage
│ ├── README.md
│ ├── data
│ └── temp
└── uv.lock
今回はhello.py
やassets
ディレクトリ、storage
ディレクトリは使用しませんが、削除しなくても問題ありません。
コード
Fletのドキュメントのサンプルコードを参考に、src
ディレクトリ内のmain.py
を書き換えました。
アメリカ地質調査所(USGS)のリアルタイムフィードから地震情報を取得し、描画するようにします。対象とする期間や地震の規模によっていくつかのフィードがありますが、今回は過去30日間の重大な地震(significant earthquakes)[2]を取得します。詳細はドキュメントをご確認ください。
コード全体を確認する
from datetime import datetime, timedelta, timezone
import flet as ft
import flet.map as map
import requests
EARTHQUAKE_URL = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.geojson'
JST = timezone(timedelta(hours=+9), 'JST')
def fetch_earthquake_data(url):
response = requests.get(url)
return response.json()
def format_earthquake_info(time, magnitude, depth):
return f'Time: {time.strftime("%Y-%m-%d %H:%M:%S")} JST\nMagnitude: {magnitude}\nDepth: {depth} km'
def create_marker(latitude, longitude, earthquake_info):
return map.Marker(
content=ft.Icon(
ft.Icons.CIRCLE,
color=ft.Colors.RED,
tooltip=earthquake_info,
),
coordinates=map.MapLatitudeLongitude(latitude, longitude),
)
def add_earthquake_markers(marker_layer, earthquake_data):
for earthquake in earthquake_data['features']:
longitude = earthquake['geometry']['coordinates'][0]
latitude = earthquake['geometry']['coordinates'][1]
depth = earthquake['geometry']['coordinates'][2]
magnitude = earthquake['properties']['mag']
time = datetime.fromtimestamp(earthquake['properties']['time'] / 1000, JST)
earthquake_info = format_earthquake_info(time, magnitude, depth)
marker_layer.current.markers.append(
create_marker(latitude, longitude, earthquake_info)
)
def refresh_data(page, marker_layer_ref):
earthquake_data = fetch_earthquake_data(EARTHQUAKE_URL)
marker_layer_ref.current.markers.clear()
add_earthquake_markers(marker_layer_ref, earthquake_data)
page.update()
def setup_page(page, marker_layer_ref):
page.title = 'Earthquake Map'
page.appbar = ft.AppBar(
title=ft.Text('Significant Earthquakes in the Past 30 Days'),
bgcolor=ft.Colors.LIGHT_BLUE_ACCENT_700,
actions=[
ft.IconButton(
ft.Icons.REFRESH,
on_click=lambda e: refresh_data(page, marker_layer_ref),
),
],
)
page.add(
ft.Text('Hover over the markers to see the earthquake information.'),
map.Map(
expand=True,
initial_zoom=2,
interaction_configuration=map.MapInteractionConfiguration(
flags=map.MapInteractiveFlag.ALL,
),
on_init=lambda e: print('Initialized Map'),
layers=[
map.TileLayer(
url_template='https://tile.openstreetmap.org/{z}/{x}/{y}.png',
on_image_error=lambda e: print('TileLayer Error'),
),
map.RichAttribution(
attributions=[
map.TextSourceAttribution(
text='OpenStreetMap Contributors',
on_click=lambda e: e.page.launch_url(
'https://openstreetmap.org/copyright',
),
),
map.TextSourceAttribution(
text="U.S. Geological Survey",
on_click=lambda e: e.page.launch_url(
"https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php",
),
),
map.TextSourceAttribution(
text='Flet',
on_click=lambda e: e.page.launch_url(
'https://flet.dev'
),
),
],
),
map.MarkerLayer(
ref=marker_layer_ref,
markers=[],
),
],
),
)
def main(page: ft.Page):
marker_layer_ref = ft.Ref[map.MarkerLayer]()
setup_page(page, marker_layer_ref)
refresh_data(page, marker_layer_ref)
ft.app(main)
実行結果
まずはデスクトップアプリケーションとして実行してみます。
uv run flet run
震央を表す円をホバーすると、詳細情報が表示されます。
画面右下のアイコンをクリックすると、出典が表示されます。
次に、Webアプリケーションとして実行してみます。
uv run flet run --web --port 8000
http://localhost:8000/ に接続すると、下記のように表示されます。
デスクトップ版と同じ内容を表示できました!
なお、今回は実施しませんが、アプリケーションを公開・配布する際にはビルドすることになります。Flutter SDKをインストールなどの準備が必要です。詳細はドキュメントを参照ください。
おわりに
この記事では、Fletを使用してマップに地震情報を表示してみました。
はじめてFletを触ってみましたが、クロスプラットフォーム対応なだけでなく、PySimpleGUIなどのGUIライブラリと比較しても、モダンなデザインのアプリケーションが作りやすそうな印象を受けました。機会があれば、活用していきたいです。
-
uvのインストール方法についてはこちらを参照ください https://docs.astral.sh/uv/getting-started/installation/ ↩︎
-
USGSによる定義 https://earthquake.usgs.gov/earthquakes/browse/significant.php#sigdef ↩︎
Discussion