document.addEventListener('DOMContentLoaded', () => { // 地図オブジェクトを作成し、中心座標とズームレベルを設定 const map = L.map('map').setView([38.9175, 139.8353], 16); const markers = [];// 全てのマーカーを保存する配列(フィルタ用) // 地図タイルを読み込み(OpenStreetMap使用) L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); // 現在地表示 if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(position => { const lat = position.coords.latitude; const lng = position.coords.longitude; L.marker([lat, lng], { icon: L.icon({ iconUrl: 'images/favicon-32x32-now.png', iconSize: [24, 24], iconAnchor: [12, 12] }) }).addTo(map).bindPopup('現在地'); }); } // ───── CSVファイルから店舗情報を読み込んでマーカーを配置 ───── fetch('snack.csv') .then(response => response.text()) .then(text => { const rows = text.split('\n').filter(row => row.trim()); const headers = rows[0].split(',').map(h => h.trim()); for (let i = 1; i < rows.length; i++) { const values = rows[i].split(',').map(v => v.replace(/^"|"$/g, '').trim()); const data = {}; headers.forEach((key, index) => data[key] = values[index] || ''); const lat = parseFloat(data.latitude); const lng = parseFloat(data.longitude); if (isNaN(lat) || isNaN(lng)) continue; // 営業中アイコンか、休業中アイコンを選択 const isOpen = !isClosedToday(data.description1) && isOpenNow(data.description2); const iconPath = isOpen ? (data.icon || 'images/snack-icon.png') : 'images/favicon-door-32x32.png'; const customIcon = L.icon({ iconUrl: iconPath, iconSize: [32, 32], iconAnchor: [16, 32], popupAnchor: [0, -32] }); // 店舗の説明文と画像 const description = [data.description1, data.description2, data.description3, data.mama] .filter(Boolean) .map(d => d.trim()) .join('<br>'); const image1 = data.img1 && data.img1.trim() !== '' ? data.img1 : 'images/snacktitle.png'; const image2 = data.img2 && data.img2.trim() !== '' ? data.img2 : 'images/snacktitle.png'; // ポップアップのHTML内容 const popupContent = ` <div class="popup-content"> <h3>${data.name.replace(/"$/, '')}</h3> <p>${description}</p> <img src="${image1}" width="106" height="73" style="cursor: pointer;" onclick="openModal('${image1}')" /> <img src="${image2}" width="106" height="73" style="cursor: pointer;" onclick="openModal('${image2}')" /> <button onclick="addToFavorites('${data.name}')">行きたいお店リストに追加</button> </div>`; const marker = L.marker([lat, lng], { icon: customIcon }).addTo(map).bindPopup(popupContent); marker.isOpen = isOpen; markers.push(marker);// フィルタ機能のために保存 } }) .catch(error => { console.error('CSV読み込みエラー:', error); }); // ───── 「空いてる店だけ表示」ボタンのUIと機能 ───── const toggleBtn = document.createElement('button'); toggleBtn.textContent = '営業中の店を表示'; toggleBtn.style.position = 'absolute'; toggleBtn.style.top = '10px'; toggleBtn.style.right = '10px'; toggleBtn.style.zIndex = 1000; toggleBtn.style.padding = '10px 10px'; toggleBtn.style.background = '#f3e8ff'; toggleBtn.style.color = '#3e004f'; toggleBtn.style.border = '1px solid #3e004f'; toggleBtn.style.cursor = 'pointer'; document.body.appendChild(toggleBtn); let showingOnlyOpen = false; toggleBtn.addEventListener('click', () => { showingOnlyOpen = !showingOnlyOpen; toggleBtn.textContent = showingOnlyOpen ? '全ての店を表示' : '営業中の店を表示'; markers.forEach(marker => { if (showingOnlyOpen) { if (marker.isOpen) marker.addTo(map); else map.removeLayer(marker); } else { marker.addTo(map); } }); }); }); // ローカルストレージに店舗名を追加(お気に入り機能) window.addToFavorites = function(name) { const favorites = JSON.parse(localStorage.getItem('favorites') || '[]'); favorites.push({ name, addedAt: new Date().toISOString() }); localStorage.setItem('favorites', JSON.stringify(favorites)); alert(`${name}を行きたいお店リストに追加しました!`); }; // 画像モーダル表示用 window.openModal = function(src) { const modal = document.getElementById("modal"); const modalImg = document.getElementById("modal-img"); modal.style.display = "block"; modalImg.src = src; }; // モーダル閉じる window.closeModal = function() { document.getElementById("modal").style.display = "none"; };