Newer
Older
2024-Ikarashi / stamp-rally.js
// 地図の初期化
const map = L.map('map').setView([38.9122, 139.8360], 12);

// タイルレイヤー(国土地理院)
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
  attribution: '<a href="https://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
  maxZoom: 18,
  minZoom: 5
}).addTo(map);

// スタンプスポット
const stampSpots = [
  { name: "かっぱ寿司 酒田店", lat: 38.9275, lng: 139.8361 },
  { name: "かっぱ寿司 鶴岡店", lat: 38.7276, lng: 139.8275 }
];

// 保存されたスタンプ情報を取得
function getSavedStamps() {
  return JSON.parse(localStorage.getItem("stamps")) || {};
}

// スタンプ取得状況を保存
function saveStamp(name) {
  const stamps = getSavedStamps();
  stamps[name] = true;
  localStorage.setItem("stamps", JSON.stringify(stamps));
}

// 地点に近いかを判定(メートル単位)
function isWithinRange(lat1, lng1, lat2, lng2, rangeMeters = 300) {
  const R = 6371000; // 地球の半径(m)
  const toRad = deg => deg * (Math.PI / 180);
  const dLat = toRad(lat2 - lat1);
  const dLng = toRad(lng2 - lng1);

  const a = Math.sin(dLat / 2) ** 2 +
            Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
            Math.sin(dLng / 2) ** 2;
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return R * c <= rangeMeters;
}

// スタンプスポットを地図に追加(取得済みかどうかを反映)
function addStampMarkers() {
  const stamps = getSavedStamps();

  stampSpots.forEach(spot => {
    const marker = L.marker([spot.lat, spot.lng], {
      icon: L.icon({
        iconUrl: stamps[spot.name] ? 'stamp-icon-on.png' : 'stamp-icon-off.png',
        iconSize: [32, 32]
      })
    }).addTo(map);

    marker.bindPopup(`${spot.name}<br>${stamps[spot.name] ? "✅ スタンプ獲得済み" : "📍 まだ獲得していません"}`);
  });
}

// 現在地と照合してスタンプ取得チェック
function checkCurrentLocationForStamp() {
  if (!navigator.geolocation) {
    alert("この端末では位置情報が取得できません。");
    return;
  }

  navigator.geolocation.getCurrentPosition(position => {
    const userLat = position.coords.latitude;
    const userLng = position.coords.longitude;

    // 現在地マーカーを追加
    L.marker([userLat, userLng], {
      icon: L.icon({
        iconUrl: 'current-location-icon.png',  // 現在地アイコン(適宜画像を用意)
        iconSize: [24, 24]
      })
    }).addTo(map).bindPopup("📍 現在地").openPopup();

    const stamps = getSavedStamps();
    let newStampEarned = false;

    stampSpots.forEach(spot => {
      if (!stamps[spot.name] && isWithinRange(userLat, userLng, spot.lat, spot.lng)) {
        saveStamp(spot.name);
        newStampEarned = true;
        alert(`🎉 ${spot.name} に到着!スタンプを獲得しました!`);
      }
    });

    if (!newStampEarned) {
      alert("スタンプスポットの範囲内にいません。");
    }

    // 再描画(獲得済みアイコンへ)
    map.eachLayer(layer => {
      if (layer instanceof L.Marker) {
        map.removeLayer(layer);
      }
    });
    addStampMarkers();

  }, () => {
    alert("位置情報の取得に失敗しました。");
  });
}

// 初期処理
window.addEventListener('load', () => {
  addStampMarkers();
  checkCurrentLocationForStamp();
});