地震情報モニターの技術解説|リアルタイムデータ表示の実装

記事のアイキャッチ画像

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秒でも早く正確な情報を得ることが、適切な判断につながります。このツールが、少しでも多くの方の安全に貢献できれば幸いです。

📚 関連記事

この記事が役に立ったら、ぜひシェアしてください!