diff --git a/map4.js b/map4.js index 95f4ae9..4231c1b 100644 --- a/map4.js +++ b/map4.js @@ -20,16 +20,11 @@ let map; let selfMarker = null; let otherMarkers = []; -let latestByDevice = {}; +let lastLat, lastLng; -let lastLat = null; -let lastLng = null; +const DEFAULT_LAT = 35.681236; +const DEFAULT_LNG = 139.767125; -const DEFAULT_LAT = 35.685175; -const DEFAULT_LNG = 139.752799; - -// =================================== -// URL 読み込み // =================================== function loadParams() { const p = new URLSearchParams(location.search); @@ -41,34 +36,29 @@ } // =================================== -// アイコン -// =================================== function createIcon(type) { return L.icon({ - iconUrl: type === "self" - ? "https://maps.gstatic.com/mapfiles/kml/paddle/blu-stars.png" - : "https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-green.png", + iconUrl: + type === "self" + ? "https://maps.gstatic.com/mapfiles/kml/paddle/blu-stars.png" + : "https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-green.png", iconSize: [40, 55], iconAnchor: [20, 50], }); } // =================================== -// GPS -// =================================== function getPosition() { - return new Promise((res, rej) => { + return new Promise((resolve, reject) => { navigator.geolocation.getCurrentPosition( - pos => res(pos.coords), - rej, + pos => resolve(pos.coords), + reject, { enableHighAccuracy: true } ); }); } // =================================== -// 地図初期化 -// =================================== function initMap(lat, lng) { map = L.map("map").setView([lat, lng], 15); @@ -78,29 +68,9 @@ } // =================================== -// 自分のピン -// =================================== -function renderSelfMarker() { - if (selfMarker) map.removeLayer(selfMarker); - - selfMarker = L.marker([lastLat, lastLng], { - icon: createIcon("self"), - }).addTo(map); - - selfMarker.bindPopup(`${currentUser}(あなた)`); - - // ★ 中心移動は e.latlng を必ず使う - selfMarker.on("click", (e) => { - map.panTo(e.latlng, { animate: true, duration: 0.4 }); - selfMarker.openPopup(); - }); -} - -// =================================== -// DB 保存 -// =================================== async function saveMyLocation(lat, lng) { - await supa.from("locations") + await supa + .from("locations") .delete() .eq("group_name", currentGroup) .eq("device_id", deviceId); @@ -115,32 +85,38 @@ } // =================================== -// メンバー一覧 +function renderSelfMarker() { + if (selfMarker) map.removeLayer(selfMarker); + + selfMarker = L.marker([lastLat, lastLng], { + icon: createIcon("self") + }).addTo(map); + + selfMarker.bindPopup(`${currentUser}(あなた)`); + + selfMarker.on("click", () => { + map.setView(selfMarker.getLatLng(), 17, { animate: true }); + selfMarker.openPopup(); + }); +} + // =================================== -function showMemberList(latestByDevice) { +function showMemberList(latest) { const list = document.getElementById("memberList"); list.innerHTML = ""; - Object.values(latestByDevice).forEach(row => { + Object.values(latest).forEach(row => { const li = document.createElement("li"); + li.textContent = row.user_name; - const diff = (Date.now() - new Date(row.updated_at)) / 1000; - li.classList.add(diff < 30 ? "online" : "offline"); - - const icon = document.createElement("div"); - icon.className = "member-icon"; - li.append(icon); - - li.append(row.user_name); - - li.addEventListener("click", () => { + li.onclick = () => { if (row.device_id === deviceId) { - if (selfMarker) selfMarker.fire("click"); - return; + selfMarker.fire("click"); + } else { + const mk = otherMarkers.find(m => m._deviceId === row.device_id); + if (mk) mk.fire("click"); } - const mk = otherMarkers.find(m => m._myDeviceId === row.device_id); - if (mk) mk.fire("click"); - }); + }; list.appendChild(li); }); @@ -151,36 +127,29 @@ const { data } = await supa .from("locations") .select("*") - .eq("group_name", currentGroup) - .order("updated_at", { ascending: false }); + .eq("group_name", currentGroup); - latestByDevice = {}; - if (!Array.isArray(data)) return; + const latest = {}; + data.forEach(row => { + if (!latest[row.device_id]) latest[row.device_id] = row; + }); - for (const row of data) { - if (!latestByDevice[row.device_id]) { - latestByDevice[row.device_id] = row; - } - } - - showMemberList(latestByDevice); + showMemberList(latest); otherMarkers.forEach(m => map.removeLayer(m)); otherMarkers = []; - Object.values(latestByDevice).forEach(row => { + Object.values(latest).forEach(row => { if (row.device_id === deviceId) return; const mk = L.marker([row.lat, row.lng], { - icon: createIcon("other"), + icon: createIcon("other") }).addTo(map); - mk._myDeviceId = row.device_id; + mk._deviceId = row.device_id; - mk.bindPopup(`${row.user_name}`); - - mk.on("click", (e) => { - map.panTo(e.latlng, { animate: true, duration: 0.4 }); + mk.on("click", () => { + map.setView([row.lat, row.lng], 17, { animate: true }); mk.openPopup(); }); @@ -189,18 +158,14 @@ } // =================================== -// main -// =================================== async function main() { loadParams(); - let lat = DEFAULT_LAT; - let lng = DEFAULT_LNG; - + let lat = DEFAULT_LAT, lng = DEFAULT_LNG; try { - const pos = await getPosition(); - lat = pos.latitude; - lng = pos.longitude; + const p = await getPosition(); + lat = p.latitude; + lng = p.longitude; } catch {} lastLat = lat; @@ -209,13 +174,14 @@ initMap(lat, lng); renderSelfMarker(); await saveMyLocation(lat, lng); + await showOtherUsers(); setInterval(async () => { try { - const pos = await getPosition(); - lastLat = pos.latitude; - lastLng = pos.longitude; + const p = await getPosition(); + lastLat = p.latitude; + lastLng = p.longitude; renderSelfMarker(); await saveMyLocation(lastLat, lastLng); } catch {} @@ -223,13 +189,10 @@ setInterval(showOtherUsers, 2000); - document.getElementById("exitBtn").onclick = - () => (location.href = "index.html"); + document.getElementById("exitBtn").onclick = () => + (location.href = "index.html"); - // ★ 地図サイズの最終調整(超重要) - setTimeout(() => { - map.invalidateSize(); - }, 500); + setTimeout(() => map.invalidateSize(), 300); } window.addEventListener("DOMContentLoaded", main);