diff --git a/map4.js b/map4.js index f41608a..8813bc6 100644 --- a/map4.js +++ b/map4.js @@ -8,7 +8,7 @@ const supa = window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY); // =============================== -// デバイスID(固定保存) +// デバイスID(このブラウザ用の固定ID) // =============================== let deviceId = localStorage.getItem("deviceId"); if (!deviceId) { @@ -16,6 +16,9 @@ localStorage.setItem("deviceId", deviceId); } +// =============================== +// グローバル変数 +// =============================== let currentGroup = ""; let currentUser = ""; let map; @@ -23,16 +26,19 @@ let otherMarkers = []; let latestByDevice = {}; +let lastLat = null; +let lastLng = null; + const DEFAULT_LAT = 35.685175; const DEFAULT_LNG = 139.752799; // =============================== -// URLパラメータ +// URLパラメータ読み込み // =============================== function loadParams() { const params = new URLSearchParams(location.search); - currentGroup = params.get("group"); - currentUser = params.get("user"); + currentGroup = params.get("group") || ""; + currentUser = params.get("user") || ""; document.getElementById("groupName").textContent = currentGroup; document.getElementById("userName").textContent = currentUser; @@ -62,7 +68,7 @@ return new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition( (pos) => resolve(pos.coords), - reject, + (err) => reject(err), { enableHighAccuracy: true } ); }); @@ -83,9 +89,11 @@ } // =============================== -// 自分の位置を保存(1件だけ) +// 自分の位置を保存(常に1件だけ) // =============================== async function saveMyLocation(lat, lng) { + if (!currentGroup) return; + await supa .from("locations") .delete() @@ -111,23 +119,21 @@ Object.values(latestByDevice).forEach((row) => { const li = document.createElement("li"); - // オンライン判定(10秒以内) + // オンライン判定(15秒以内) const updated = new Date(row.updated_at); const now = new Date(); const diff = (now - updated) / 1000; + li.classList.add(diff < 15 ? "online" : "offline"); - li.classList.add(diff < 10 ? "online" : "offline"); - - // アイコン const icon = document.createElement("div"); icon.className = "member-icon"; li.appendChild(icon); li.append(row.user_name); - // ★ メンバークリック → ピンにズーム & ピンを跳ねさせる + // メンバークリックでその人のピンへズーム li.addEventListener("click", () => { - if (row.lat && row.lng) { + if (row.lat != null && row.lng != null) { map.setView([row.lat, row.lng], 16, { animate: true }); const marker = otherMarkers.find(m => m._myDeviceId === row.device_id); @@ -147,16 +153,18 @@ // 他ユーザーのピン表示 // =============================== async function showOtherUsers() { - const { data, error } = await supa .from("locations") .select("*") .eq("group_name", currentGroup) .order("updated_at", { ascending: false }); - if (error || !data) return; + if (error || !Array.isArray(data)) { + console.error("Supabase error:", error); + return; + } - // 最新データを1デバイス1件に + // デバイスごとに最新1件のみ latestByDevice = {}; for (const row of data) { if (!latestByDevice[row.device_id]) { @@ -164,13 +172,13 @@ } } - // ★ 自分のデータがないことがある → 強制追加 + // 念のため自分が含まれない場合は追加(表示用) if (!latestByDevice[deviceId]) { latestByDevice[deviceId] = { user_name: currentUser, device_id: deviceId, - lat: null, - lng: null, + lat: lastLat, + lng: lastLng, updated_at: new Date().toISOString() }; } @@ -178,12 +186,13 @@ // メンバー一覧更新 showMemberList(latestByDevice); - // ピン再描画(他人のみ) + // ピン更新(他人のみ) otherMarkers.forEach((m) => map.removeLayer(m)); otherMarkers = []; Object.values(latestByDevice).forEach((row) => { if (row.device_id === deviceId) return; + if (row.lat == null || row.lng == null) return; const mk = L.marker([row.lat, row.lng], { icon: otherIcon }).addTo(map); mk._myDeviceId = row.device_id; @@ -204,20 +213,40 @@ const pos = await getPosition(); lat = pos.latitude; lng = pos.longitude; - } catch {} + } catch (e) { + console.warn("現在地取得に失敗。デフォルト位置を使用します。", e); + } + + lastLat = lat; + lastLng = lng; initMap(lat, lng); - await saveMyLocation(lat, lng); + await saveMyLocation(lastLat, lastLng); await showOtherUsers(); - // 2秒ごとに更新 + // 🔁 自分の位置を5秒ごとに更新(オンライン維持用) + setInterval(async () => { + try { + const pos = await getPosition(); + lastLat = pos.latitude; + lastLng = pos.longitude; + await saveMyLocation(lastLat, lastLng); + } catch (e) { + // 取得失敗しても無視してOK + } + }, 5000); + + // 🔁 他のメンバーの位置とオンライン状況を2秒ごとに更新 setInterval(showOtherUsers, 2000); // 退出ボタン - document.getElementById("exitBtn").onclick = () => { - location.href = "index.html"; - }; + const exitBtn = document.getElementById("exitBtn"); + if (exitBtn) { + exitBtn.onclick = () => { + location.href = "index.html"; + }; + } } window.addEventListener("DOMContentLoaded", main);