diff --git a/shonai_tiiki_map_tansaku.js b/shonai_tiiki_map_tansaku.js
index 453e8ba..a6369ed 100644
--- a/shonai_tiiki_map_tansaku.js
+++ b/shonai_tiiki_map_tansaku.js
@@ -1,52 +1,52 @@
document.addEventListener("DOMContentLoaded", () => {
var mymap = L.map("locationmap").setView([38.855235,139.910744], 16);
-
+
L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(mymap);
-
+
var playerIcon = L.icon({
iconUrl: 'images/yuusya.png',
iconSize: [40, 40],
iconAnchor: [20, 40],
popupAnchor: [0, -40]
});
-
+
var locmarker = L.marker(mymap.getCenter(), { icon: playerIcon }).addTo(mymap);
locmarker.bindPopup("STARTを押してね").openPopup();
-
+
let circleRadius = 500;
let goalReachRadius = 10;
-
+
var radiusCircle = L.circle(mymap.getCenter(), {
radius: circleRadius,
color: 'blue',
fillColor: 'blue',
fillOpacity: 0.1
}).addTo(mymap);
-
+
var watchId = null;
const urlParams = new URLSearchParams(window.location.search);
const cheatMode = urlParams.get("cheat") === "true";
-
+
let stores = [];
let visitedStores = [];
let storeMarkers = [];
-
+
const canvas = document.getElementById("progressImage");
const ctx = canvas.getContext("2d");
const totalImages = 7;
const images = [];
-
+
for (let i = 0; i < totalImages; i++) {
images[i] = new Image();
images[i].src = `images/irasuto${i + 1}.png`;
}
-
+
function saveProgress() {
localStorage.setItem("visitedStores", JSON.stringify(visitedStores));
}
-
+
function loadProgress() {
const saved = localStorage.getItem("visitedStores");
if (saved) {
@@ -56,18 +56,18 @@
} catch (e) { console.error("保存データの読み込みに失敗:", e); }
}
}
-
+
function updateProgressImage() {
if (!canvas) return;
-
+
let storeTotal = stores.length > 0 ? stores.length : 1;
let progress = visitedStores.length / storeTotal;
-
+
let index = Math.floor(progress * totalImages);
if (index >= totalImages) index = totalImages - 1;
-
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
-
+
if (images[index].complete) {
ctx.drawImage(images[index], 0, 0, canvas.width, canvas.height);
} else {
@@ -76,7 +76,7 @@
};
}
}
-
+
function renderBookmarkList() {
const container = document.getElementById("bookmarkList");
container.innerHTML = "";
@@ -87,7 +87,7 @@
visitedStores.forEach((store, idx) => {
const div = document.createElement("div");
div.className = "bookmark-item";
-
+
div.innerHTML = `
${store.name} (訪問日時: ${store.time})
おすすめ: ${store.osusume || "〇〇"}
@@ -100,7 +100,7 @@
`;
container.appendChild(div);
});
-
+
const memos = container.querySelectorAll(".memo-textarea");
memos.forEach(textarea => {
textarea.addEventListener("input", (e) => {
@@ -109,25 +109,25 @@
saveProgress();
});
});
-
+
const uploads = container.querySelectorAll(".image-upload");
uploads.forEach(input => {
input.addEventListener("change", (e) => {
const index = e.target.dataset.index;
const file = e.target.files[0];
if (!file) return;
-
+
if (file.size > 5 * 1024 * 1024) {
alert("ファイルサイズは5MB以下にしてください。");
e.target.value = "";
return;
}
-
+
const reader = new FileReader();
reader.onload = function(event) {
visitedStores[index].image = event.target.result;
saveProgress();
-
+
const img = e.target.parentElement.querySelector(".preview-image");
if (img) {
img.src = event.target.result;
@@ -137,7 +137,7 @@
reader.readAsDataURL(file);
});
});
-
+
const deletes = container.querySelectorAll(".image-delete");
deletes.forEach(button => {
button.addEventListener("click", (e) => {
@@ -156,9 +156,9 @@
});
});
}
-
+
function loadCSV() {
- fetch('shonai_tiiki_map.csv')
+ fetch('shonai_tiiki_map_tansaku.csv')
.then(res => res.ok ? res.text() : Promise.reject("CSV読み込み失敗"))
.then(csvText => {
const results = Papa.parse(csvText, { header: true, skipEmptyLines: true });
@@ -172,7 +172,8 @@
marker: null,
redCircle: null
})).filter(s => !isNaN(s.latitude) && !isNaN(s.longitude));
-
+
+ // 既に訪問済みの店舗をマップへ復元(画像対応版)
visitedStores.forEach(obj => {
const s = stores.find(st => st.name === obj.name);
if (s) {
@@ -185,7 +186,7 @@
let popupContent = `
訪問日時: ${obj.time}
庄内総合高校の子のおすすめは${obj.osusume || "〇〇"}
- ${s.osusumeImage ? `
` : ""}
+ ${s.osusumeImage ? `
` : ""}
`;
let storeMarker = L.marker([s.latitude, s.longitude], { icon: customIcon })
.addTo(mymap)
@@ -193,7 +194,7 @@
storeMarkers.push(storeMarker);
}
});
-
+
if (cheatMode) {
document.getElementById("title").textContent = "チートモード";
mymap.on("click", e => updateLocation(e.latlng));
@@ -203,11 +204,11 @@
})
.catch(err => alert("CSVの読み込みに失敗しました: " + err));
}
-
+
function getDistance(lat1, lng1, lat2, lng2) {
return L.latLng(lat1, lng1).distanceTo(L.latLng(lat2, lng2));
}
-
+
function getNearestStore(latlng) {
let nearest = null, minDist = Infinity;
for (let s of stores) {
@@ -218,28 +219,30 @@
if (!nearest) return null;
return { store: nearest, distance: minDist };
}
-
+
function updateLocation(latlng) {
mymap.panTo(latlng);
locmarker.setLatLng(latlng);
radiusCircle.setLatLng(latlng);
-
+
stores.forEach(s => {
const d = getDistance(latlng.lat, latlng.lng, s.latitude, s.longitude);
-
+
if (visitedStores.some(c => c.name === s.name)) {
if (s.marker && mymap.hasLayer(s.marker)) mymap.removeLayer(s.marker);
if (s.redCircle && mymap.hasLayer(s.redCircle)) mymap.removeLayer(s.redCircle);
return;
}
-
+
if (d <= circleRadius) {
if (!s.marker) {
- s.marker = L.marker([s.latitude, s.longitude]).addTo(mymap).bindPopup(s.name);
+ s.marker = L.marker([s.latitude, s.longitude])
+ .addTo(mymap)
+ .bindPopup(s.name);
} else if (!mymap.hasLayer(s.marker)) {
s.marker.addTo(mymap);
}
-
+
if (!s.redCircle) {
s.redCircle = L.circle([s.latitude, s.longitude], {
radius: goalReachRadius,
@@ -258,15 +261,15 @@
if (s.redCircle && mymap.hasLayer(s.redCircle)) mymap.removeLayer(s.redCircle);
}
});
-
+
let nearestData = getNearestStore(latlng);
if (!nearestData) {
locmarker.setPopupContent("すべての店舗を訪問しました!").openPopup();
return;
}
-
+
const { store, distance } = nearestData;
-
+
if (distance <= goalReachRadius) {
const now = new Date();
const options = {
@@ -275,39 +278,48 @@
};
const visitTime = now.toLocaleString('ja-JP', options);
const recommendation = store.osusume.trim() !== "" ? store.osusume : "〇〇";
-
- locmarker.setPopupContent(
- `到着!(${store.name})
訪問日時: ${visitTime}
庄内総合高校の子のおすすめは${recommendation}`
- ).openPopup();
-
- visitedStores.push({ name: store.name, time: visitTime, osusume: recommendation });
+
+ // ===画像付きポップアップに修正した部分===
+ let popupHTML = `
+ 到着!(${store.name})
+ 訪問日時: ${visitTime}
+ 庄内総合高校の子のおすすめは${recommendation}
+ ${store.osusumeImage ? `
` : ""}
+ `;
+ locmarker.setPopupContent(popupHTML).openPopup();
+
+ visitedStores.push({
+ name: store.name,
+ time: visitTime,
+ osusume: recommendation
+ });
saveProgress();
-
+
if (store.marker && mymap.hasLayer(store.marker)) mymap.removeLayer(store.marker);
if (store.redCircle && mymap.hasLayer(store.redCircle)) mymap.removeLayer(store.redCircle);
-
+
const customIcon = L.icon({
iconUrl: store.iconUrl,
iconSize: [40, 40],
iconAnchor: [20, 40],
popupAnchor: [0, -40]
});
-
+
let newMarker = L.marker([store.latitude, store.longitude], { icon: customIcon })
.addTo(mymap)
- .bindPopup(`訪問日時: ${visitTime}
庄内総合高校の子のおすすめは${recommendation}`);
+ .bindPopup(popupHTML, {autoClose:false});
storeMarkers.push(newMarker);
-
+
updateProgressImage();
renderBookmarkList();
-
+
} else if (distance <= circleRadius) {
locmarker.setPopupContent(`もう少しで${store.name}!`).openPopup();
} else {
locmarker.setPopupContent(`ここは lat=${latlng.lat.toFixed(5)}, lng=${latlng.lng.toFixed(5)} です.`).openPopup();
}
}
-
+
function resetProgress() {
if (confirm("進行状況をリセットして最初からやり直しますか?")) {
localStorage.removeItem("visitedStores");
@@ -320,10 +332,10 @@
location.reload();
}
}
-
+
loadProgress();
loadCSV();
-
+
if (!cheatMode) {
document.getElementById("start").addEventListener("click", () => {
watchId = navigator.geolocation.watchPosition(
@@ -333,42 +345,42 @@
);
});
}
-
+
document.getElementById("stop").addEventListener("click", () => {
if (watchId != null) navigator.geolocation.clearWatch(watchId);
watchId = null;
});
document.getElementById("reset").addEventListener("click", resetProgress);
-
+
const radiusSelect = document.getElementById("radiusSelect");
const goalSelect = document.getElementById("goalSelect");
const RADIUS_KEY = "selectedRadius";
const GOAL_KEY = "selectedGoal";
-
+
let savedRadius = localStorage.getItem(RADIUS_KEY);
if (savedRadius) {
circleRadius = parseInt(savedRadius, 10);
radiusCircle.setRadius(circleRadius);
radiusSelect.value = savedRadius;
}
-
+
let savedGoal = localStorage.getItem(GOAL_KEY);
if (savedGoal) {
goalReachRadius = parseInt(savedGoal, 10);
goalSelect.value = savedGoal;
}
-
+
radiusSelect.addEventListener("change", (e) => {
circleRadius = parseInt(e.target.value, 10);
radiusCircle.setRadius(circleRadius);
localStorage.setItem(RADIUS_KEY, circleRadius);
});
-
+
goalSelect.addEventListener("change", (e) => {
goalReachRadius = parseInt(e.target.value, 10);
localStorage.setItem(GOAL_KEY, goalReachRadius);
-
+
stores.forEach(s => {
if (s.redCircle) {
s.redCircle.setRadius(goalReachRadius);