Skip to content

イベント処理

Japan Map Selectorは様々なイベントを提供し、インタラクティブな地図アプリケーションの構築を可能にします。

コールバック関数

基本的な使い方

javascript
const map = new JapanMapSelector({
  onPrefectureSelect: (prefecture) => {
    console.log('都道府県が選択されました:', prefecture.name);
  },
  onMunicipalitySelect: (municipality) => {
    console.log('市区町村が選択されました:', municipality.name);
  }
});

Prefectureオブジェクト

onPrefectureSelectコールバックで受け取るオブジェクト:

typescript
interface Prefecture {
  code: string;        // 都道府県コード(例: '13')
  name: string;        // 都道府県名(例: '東京都')
  bounds: [[number, number], [number, number]]; // 境界ボックス
  feature: GeoJSONFeature; // GeoJSONフィーチャー
}

Municipalityオブジェクト

onMunicipalitySelectコールバックで受け取るオブジェクト:

typescript
interface Municipality {
  code: string;         // 市区町村コード
  name: string;         // 市区町村名
  prefectureCode: string; // 都道府県コード
  feature: GeoJSONFeature; // GeoJSONフィーチャー
}

イベントリスナー

カスタムイベントの購読

javascript
// イベントリスナーを追加
map.on('stateChanged', (state) => {
  console.log('地図の状態が変更されました:', state);
});

map.on('prefectureSelected', (prefecture) => {
  console.log('都道府県選択イベント:', prefecture.name);
});

map.on('municipalitySelected', (municipality) => {
  console.log('市区町村選択イベント:', municipality.name);
});

// イベントリスナーを削除
const handler = (state) => console.log(state);
map.on('stateChanged', handler);
map.off('stateChanged', handler);

利用可能なイベント

イベント名説明パラメータ
initialized地図データの読み込み完了なし
stateChanged地図の状態変更MapState
prefectureSelected都道府県選択Prefecture
municipalitySelected市区町村選択Municipality
themeChangedテーマ変更ColorTheme

ホバーイベント

プログラムによるホバー制御

javascript
// 都道府県をホバー
map.hoverPrefecture('13'); // 東京都をホバー
map.hoverPrefecture(null); // ホバー解除

// 市区町村をホバー
map.hoverMunicipality('13101'); // 千代田区をホバー
map.hoverMunicipality(null); // ホバー解除

ホバー状態の監視

javascript
map.on('stateChanged', (state) => {
  if (state.hoveredPrefecture) {
    console.log('ホバー中の都道府県:', state.hoveredPrefecture.name);
  }
  if (state.hoveredMunicipality) {
    console.log('ホバー中の市区町村:', state.hoveredMunicipality.name);
  }
});

実装例

選択情報の表示

javascript
// 情報パネルを更新する例
map.on('prefectureSelected', (prefecture) => {
  const infoPanel = document.getElementById('info-panel');
  infoPanel.innerHTML = `
    <h3>${prefecture.name}</h3>
    <p>都道府県コード: ${prefecture.code}</p>
    <p>市区町村を選択してください</p>
  `;
});

map.on('municipalitySelected', (municipality) => {
  const infoPanel = document.getElementById('info-panel');
  infoPanel.innerHTML = `
    <h3>${municipality.name}</h3>
    <p>市区町村コード: ${municipality.code}</p>
    <button onclick="showDetails('${municipality.code}')">
      詳細を見る
    </button>
  `;
});

選択履歴の管理

javascript
class SelectionHistory {
  constructor(map) {
    this.history = [];
    this.map = map;
    
    // イベントを監視
    map.on('prefectureSelected', (prefecture) => {
      this.addToHistory({
        type: 'prefecture',
        data: prefecture,
        timestamp: new Date()
      });
    });
    
    map.on('municipalitySelected', (municipality) => {
      this.addToHistory({
        type: 'municipality',
        data: municipality,
        timestamp: new Date()
      });
    });
  }
  
  addToHistory(entry) {
    this.history.push(entry);
    this.updateUI();
  }
  
  updateUI() {
    const historyList = document.getElementById('history-list');
    historyList.innerHTML = this.history
      .slice(-10) // 最新10件
      .reverse()
      .map(entry => `
        <li>
          ${entry.data.name} - 
          ${entry.timestamp.toLocaleTimeString()}
        </li>
      `)
      .join('');
  }
}

複数の地図の連動

javascript
// メイン地図
const mainMap = new JapanMapSelector({
  width: 800,
  height: 600
});

// サブ地図(詳細表示用)
const detailMap = new JapanMapSelector({
  width: 400,
  height: 300
});

// メイン地図の選択をサブ地図に反映
mainMap.on('prefectureSelected', (prefecture) => {
  detailMap.selectPrefecture(prefecture.code);
});

// 両方の地図でホバーを同期
mainMap.on('stateChanged', (state) => {
  if (state.hoveredPrefecture) {
    detailMap.hoverPrefecture(state.hoveredPrefecture.code);
  } else {
    detailMap.hoverPrefecture(null);
  }
});

アニメーション付き選択

javascript
// CSSアニメーションと組み合わせた選択
map.on('prefectureSelected', (prefecture) => {
  // SVGパスを取得
  const path = document.querySelector(
    `[data-prefecture="${prefecture.code}"]`
  );
  
  if (path) {
    // アニメーションクラスを追加
    path.classList.add('selected-animation');
    
    // アニメーション終了後にクラスを削除
    setTimeout(() => {
      path.classList.remove('selected-animation');
    }, 1000);
  }
});
css
.selected-animation {
  animation: pulse 1s ease-out;
}

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

エラーハンドリング

javascript
// 初期化エラーの処理
try {
  await map.initialize(prefectureUrl, municipalityUrl);
} catch (error) {
  console.error('地図の初期化に失敗しました:', error);
  
  // ユーザーに通知
  showErrorMessage('地図データの読み込みに失敗しました');
}

// 選択エラーの処理
map.on('municipalitySelected', async (municipality) => {
  try {
    const response = await fetch(`/api/data/${municipality.code}`);
    if (!response.ok) throw new Error('データ取得失敗');
    
    const data = await response.json();
    displayData(data);
  } catch (error) {
    console.error('データ取得エラー:', error);
    showErrorMessage('詳細データを取得できませんでした');
  }
});

MIT License