地震情報モニターの技術解説|リアルタイムデータ表示の実装
2024年の能登半島地震をきっかけに、リアルタイムで地震情報を確認できるツールの必要性を強く感じました。テレビをつけなくても、スマホで素早く震度や震源地を確認したい。そんな思いから開発したのが「地震情報モニター」です。この記事では、気象庁APIとの連携、リアルタイムデータ表示、そして自動更新の実装方法について、技術的な詳細を解説します。
地震情報モニターを作った背景
災害時の情報収集の課題
地震が発生した際、多くの人がスマホで情報を確認しますが、以下のような課題がありました:
- アプリのダウンロードが必要:緊急時に新しいアプリをインストールするのは手間
- 情報の遅延:ニュースサイトでは速報が遅れることがある
- 広告が邪魔:災害情報を見る際に広告が表示されるのは不適切
- 複雑な操作:緊急時にシンプルに情報を得たい
「ブラウザを開くだけで、即座に最新の地震情報が見られるツール」を目指して開発をスタートしました。
設計思想:シンプル・高速・正確
このアプリで重視した3つのポイント:
- シンプル:余計な機能は一切なし。地震情報だけを表示
- 高速:ページを開いた瞬間に情報が表示される
- 正確:気象庁の公式データを直接取得
技術選定とアーキテクチャ
全体のシステム構成
地震情報モニターは以下の構成で実装しています:
技術スタック: - フロントエンド: HTML/CSS/JavaScript (Vanilla JS) - データソース: 気象庁防災情報XML(P2P地震情報API経由) - 自動更新: Polling方式(30秒間隔) - 地図表示: Leaflet.js(オープンソース地図ライブラリ) - ホスティング: GitHub Pages
気象庁APIの選定とCORS問題
当初、気象庁の公式APIを直接使おうとしましたが、CORS(Cross-Origin Resource Sharing)の制限に直面しました。
CORS問題とは:
ブラウザのセキュリティ機能により、異なるドメインのAPIに直接アクセスできない制限です。
解決策:
- P2P地震情報APIを利用:気象庁データをJSON形式で提供してくれる中継API
- CORS対応済み:ブラウザから直接アクセス可能
- 無料・登録不要:APIキー不要で誰でも使える
// P2P地震情報APIのエンドポイント例
const API_URL = 'https://api.p2pquake.net/v2/history?codes=551&limit=10';
// データ取得
async function fetchEarthquakeData() {
const response = await fetch(API_URL);
const data = await response.json();
return data;
}
リアルタイム更新の実装
Polling vs WebSocket の選択
リアルタイムデータ更新には、主に2つの方法があります:
- Polling:一定間隔でサーバーにリクエストを送る
- WebSocket:常時接続を維持し、サーバーからpush通知を受け取る
このアプリではPolling方式を採用しました。理由は以下の通りです:
- 実装がシンプル:setIntervalで簡単に実装できる
- サーバー負荷が低い:地震は頻繁に起きないため、30秒間隔で十分
- 接続の安定性:WebSocketの接続切れを気にしなくて良い
// 30秒ごとに地震データを取得
let updateInterval;
function startAutoUpdate() {
// 初回実行
updateEarthquakeList();
// 30秒ごとに更新
updateInterval = setInterval(() => {
updateEarthquakeList();
}, 30000);
}
function stopAutoUpdate() {
if (updateInterval) {
clearInterval(updateInterval);
}
}
データの差分検出と通知
新しい地震が発生した際、ユーザーに通知する仕組みを実装しました:
- 前回取得したデータと比較
- 新しいデータがあれば、視覚的にハイライト表示
- ブラウザ通知(Notification API)でアラート
let previousEarthquakeId = null;
async function updateEarthquakeList() {
const data = await fetchEarthquakeData();
if (data.length > 0) {
const latestId = data[0].id;
// 新しい地震を検出
if (previousEarthquakeId && latestId !== previousEarthquakeId) {
showNotification(data[0]);
highlightNewEarthquake(data[0]);
}
previousEarthquakeId = latestId;
renderEarthquakeList(data);
}
}
function showNotification(earthquake) {
if ('Notification' in window && Notification.permission === 'granted') {
new Notification('地震情報', {
body: `${earthquake.earthquake.hypocenter.name} 震度${earthquake.earthquake.maxScale}`,
icon: '/earthquake-icon.png'
});
}
}
地図表示の実装(Leaflet.js)
Leaflet.jsを選んだ理由
震源地を地図上に表示するため、地図ライブラリが必要でした。Leaflet.jsを選んだ理由:
- 軽量:Google Maps APIと比べて非常に軽い(約40KB)
- 無料:APIキー不要、制限なし
- カスタマイズ性:マーカーやポップアップを自由に設定可能
- オープンソース:商用利用も可能
震源地マーカーの実装
震度に応じて、マーカーの色とサイズを変える工夫をしました:
function addEarthquakeMarker(map, earthquake) {
const lat = earthquake.earthquake.hypocenter.latitude;
const lon = earthquake.earthquake.hypocenter.longitude;
const maxScale = earthquake.earthquake.maxScale;
// 震度に応じて色とサイズを決定
const color = getColorByScale(maxScale);
const radius = getRadiusByScale(maxScale);
const marker = L.circleMarker([lat, lon], {
radius: radius,
fillColor: color,
color: '#fff',
weight: 2,
opacity: 1,
fillOpacity: 0.7
}).addTo(map);
// ポップアップ表示
marker.bindPopup(`
${earthquake.earthquake.hypocenter.name}
震度: ${maxScale}
深さ: ${earthquake.earthquake.hypocenter.depth}km
マグニチュード: ${earthquake.earthquake.magnitude}
`);
}
function getColorByScale(scale) {
if (scale >= 6) return '#ff0000'; // 震度6以上: 赤
if (scale >= 5) return '#ff6600'; // 震度5: オレンジ
if (scale >= 4) return '#ffcc00'; // 震度4: 黄色
return '#00cc00'; // 震度3以下: 緑
}
UI/UXで工夫したポイント
1. 情報の優先順位表示
最も重要な情報(最新の地震)を上部に大きく表示し、過去の地震は下にリスト表示しました。
- 最新情報カード:震度・震源地・時刻を大きく表示
- 過去10件リスト:コンパクトに表形式で表示
- 色分け:震度に応じて背景色を変更(視覚的に重要度を把握)
2. 読み込み状態の表示
データ取得中は、ユーザーに待機状態を明示:
- ローディングスピナーを表示
- 「更新中...」のテキスト表示
- 最終更新時刻を表示(データの鮮度を明示)
3. レスポンシブ対応
災害時はスマホで確認する人が多いため、モバイル最適化は必須でした:
- スマホでも見やすい大きな文字サイズ
- タップしやすいボタンサイズ(最低44px)
- 地図はスマホでもスムーズにピンチ操作可能
開発中の課題と解決策
課題1: データの信頼性確保
災害情報を扱うため、データの正確性は最重要でした。
解決策:
- 気象庁の公式データを使用するP2P地震情報APIを採用
- データ取得エラー時は、前回のデータを表示し続ける
- 「情報源: 気象庁」と明記し、透明性を確保
課題2: API制限への対応
P2P地震情報APIは無料ですが、過度なアクセスは避けるべきです。
解決策:
- Polling間隔を30秒に設定(推奨値)
- タブが非アクティブ時は更新を停止(Page Visibility API)
- 取得したデータをローカルストレージにキャッシュ
// タブが非アクティブ時は更新を停止
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
stopAutoUpdate();
} else {
startAutoUpdate();
}
});
課題3: パフォーマンス最適化
緊急時に高速表示が求められるため、パフォーマンス最適化は重要でした。
解決策:
- 画像を使わず、CSS・Unicode絵文字で軽量化
- 地図は最初は非表示、「地図を表示」ボタンで遅延読み込み
- 不要なライブラリは一切使わない
リリース後の反響と改善
ユーザーからの反応
リリース後、以下のような声をいただきました:
- 「アプリ不要でブラウザだけで使えるのが便利」
- 「シンプルで見やすい。広告がないのが良い」
- 「通知機能があるので、地震に気づきやすくなった」
実施した改善
ユーザーフィードバックを受けて、以下の機能を追加しました:
- 震度フィルター:「震度4以上のみ表示」などの絞り込み機能
- 地域フィルター:特定地域の地震のみ表示
- 音声通知:大きな地震の際にアラート音を鳴らす
- 履歴保存:過去1週間の地震データを表示
このプロジェクトで学んだこと
技術面での学び
- API連携の実践:外部APIを使った実用的なアプリ開発の経験
- リアルタイム処理:Pollingによる自動更新の実装パターン
- 地図ライブラリの活用:Leaflet.jsの基本から応用まで習得
- エラーハンドリング:災害情報アプリならではの堅牢性の重要性
社会的意義の実感
- 災害時に役立つツールの価値:技術で社会貢献できる喜び
- シンプルさの重要性:緊急時こそ、複雑な操作は不要
- 信頼性とスピードの両立:正確な情報を素早く届ける技術的挑戦
今後の展望
今後、以下の機能追加を検討しています:
- 緊急地震速報(EEW)対応:P波検知時の早期警報
- 津波情報の表示:海岸部での避難判断に役立つ情報
- PWA化:オフラインでも動作するアプリ化
- 多言語対応:訪日外国人向けの英語表示
まとめ
地震情報モニターの開発を通じて、「災害時に本当に役立つツール」の要件を学びました。このプロジェクトのポイントをまとめます:
- 公式データの活用:気象庁データを使い、信頼性を確保
- リアルタイム更新:Pollingで30秒ごとに最新情報を取得
- 地図表示:Leaflet.jsで震源地を視覚的に表示
- シンプルなUI:緊急時でも迷わない設計
- パフォーマンス最適化:高速表示で即座に情報提供
災害時、1秒でも早く正確な情報を得ることが、適切な判断につながります。このツールが、少しでも多くの方の安全に貢献できれば幸いです。
📚 関連記事
この記事が役に立ったら、ぜひシェアしてください!