document.addEventListener('DOMContentLoaded', function() { var map, layer, data = []; var urlParams = new URLSearchParams(window.location.search); var areaKey = urlParams.get('area') || 'chugoku'; var areaSettings = { 'hokkaido': { title: '北海道', center: [43.3, 142.8], zoom: 7, bounds: { minLat: 41.0, maxLat: 45.6, minLng: 139.0, maxLng: 146.0 } }, 'tohoku': { title: '東北地方', center: [39.0, 140.5], zoom: 7, bounds: { minLat: 37.0, maxLat: 41.6, minLng: 138.5, maxLng: 142.5 } }, 'kanto': { title: '関東地方', center: [36.0, 139.5], zoom: 8, bounds: { minLat: 34.5, maxLat: 37.5, minLng: 138.0, maxLng: 141.0 } }, 'koshinetsu': { title: '甲信越地方', center: [36.5, 138.0], zoom: 8, bounds: { minLat: 35.0, maxLat: 38.5, minLng: 137.0, maxLng: 139.5 } }, 'chubu': { title: '中部地方', center: [35.5, 137.0], zoom: 8, bounds: { minLat: 34.0, maxLat: 37.5, minLng: 135.5, maxLng: 138.5 } }, 'kinki': { title: '近畿地方', center: [34.5, 135.5], zoom: 8, bounds: { minLat: 33.0, maxLat: 36.0, minLng: 134.0, maxLng: 136.5 } }, 'chugoku': { title: '中国地方', center: [35.375, 133.535], zoom: 9, bounds: { minLat: 33.0, maxLat: 36.5, minLng: 130.5, maxLng: 134.5 } }, 'shikoku': { title: '四国地方', center: [33.766, 133.116], zoom: 9, bounds: { minLat: 32.5, maxLat: 34.5, minLng: 132.0, maxLng: 135.0 } }, 'kyushu': { title: '九州地方', center: [32.5, 130.5], zoom: 8, bounds: { minLat: 30.0, maxLat: 34.0, minLng: 128.0, maxLng: 132.0 } } }; var currentArea = areaSettings[areaKey] || areaSettings['chugoku']; var titleEl = document.getElementById('map-title'); if (titleEl) { titleEl.innerHTML = '⛰️ ' + currentArea.title + ' 遭難・歴史・グルメ・温泉マップ'; } window.activeMountainFilter = 'all'; window.showHuts = false; window.showParking = false; // ★追加: 駐車場表示フラグ window.showGourmet = false; // グルメ表示フラグ window.showOnsen = false; // 温泉表示フラグ // ===== 登頂チェックリスト ===== window.MountainChecklist = { KEY: 'hokkaido_climbed_v1', getAll: function() { try { return JSON.parse(localStorage.getItem(this.KEY)) || {}; } catch(e) { return {}; } }, isClimbed: function(title) { return !!this.getAll()[title]; }, toggle: function(title) { var all = this.getAll(); if (all[title]) { delete all[title]; } else { all[title] = new Date().toISOString().split('T')[0]; } localStorage.setItem(this.KEY, JSON.stringify(all)); MountainChecklist.updateBar(data); }, updateBar: function(mountainData) { var b = currentArea.bounds; var mountains = mountainData.filter(function(d) { return (d.cat === '百名山' || d.cat === '二百名山' || d.cat === '三百名山') && d.lat >= b.minLat && d.lat <= b.maxLat && d.lng >= b.minLng && d.lng <= b.maxLng; }); var all = MountainChecklist.getAll(); var done = mountains.filter(function(d) { return !!all[d.title]; }).length; var total = mountains.length; var text = document.getElementById('checklist-progress-text'); var fill = document.getElementById('checklist-bar-fill'); if (text) text.textContent = done + ' / ' + total + '座 登頂済み'; if (fill) fill.style.width = total ? (done / total * 100) + '%' : '0%'; }, share: function() { var done = Object.keys(this.getAll()).length; var text = currentArea.title + 'の山を ' + done + '座 登頂しました! #日本百名山 #登山'; window.open( 'https://twitter.com/intent/tweet?text=' + encodeURIComponent(text) + '&url=' + encodeURIComponent(location.href), '_blank' ); } }; window.handleClimbToggle = function(btn, title) { MountainChecklist.toggle(title); var isC = MountainChecklist.isClimbed(title); btn.className = 'btn-climbed ' + (isC ? 'done' : 'not-done'); btn.textContent = isC ? '✓ 登頂済み(タップで解除)' : '🏔 登頂済みにする'; }; // 山小屋トグル window.toggleHuts = function() { window.showHuts = !window.showHuts; var btn = document.getElementById('hut-toggle-btn'); if (btn) { btn.className = 'toggle-btn toggle-btn-hut ' + (window.showHuts ? 'on' : 'off'); } update(); }; // ★追加: 駐車場トグル window.toggleParking = function() { window.showParking = !window.showParking; var btn = document.getElementById('parking-toggle-btn'); if (btn) { btn.className = 'toggle-btn toggle-btn-parking ' + (window.showParking ? 'on' : 'off'); } update(); }; // グルメトグル window.toggleGourmet = function() { window.showGourmet = !window.showGourmet; var btn = document.getElementById('gourmet-toggle-btn'); if (btn) { btn.className = 'toggle-btn toggle-btn-gourmet ' + (window.showGourmet ? 'on' : 'off'); } update(); }; // 温泉トグル window.toggleOnsen = function() { window.showOnsen = !window.showOnsen; var btn = document.getElementById('onsen-toggle-btn'); if (btn) { btn.className = 'toggle-btn toggle-btn-onsen ' + (window.showOnsen ? 'on' : 'off'); } update(); }; function loadData() { Promise.all([ fetch('/wp-content/uploads/alldata.json?_t=' + Date.now()).then(function(r){ return r.json(); }), fetch('/wp-content/uploads/hut_data.json?_t=' + Date.now()).then(function(r){ return r.json(); }), fetch('/wp-content/uploads/parking_data.json?_t=' + Date.now()).then(function(r){ return r.json(); }) // ★追加 ]) .then(function(results) { var alldata = results[0]; var hutRaw = results[1]; var parkingRaw = results[2]; // ★追加 // hut_data.jsonを alldata.json と同じ形式に変換 var hutdata = []; Object.keys(hutRaw).forEach(function(mountainName) { hutRaw[mountainName].forEach(function(hut) { hutdata.push({ title: hut.name, cat: '山小屋', lat: hut.lat, lng: hut.lng, desc: mountainName + 'の山小屋', stat: '', year: '', age: '', sex: '' }); }); }); // ★追加: parking_data.jsonを alldata.json と同じ形式に変換 var parkingdata = []; Object.keys(parkingRaw).forEach(function(mountainName) { parkingRaw[mountainName].forEach(function(p) { parkingdata.push({ title: p.name, cat: '駐車場', lat: p.lat, lng: p.lng, desc: mountainName + 'の駐車場' + (p.vicinity ? '(' + p.vicinity + ')' : ''), stat: '', year: '', age: '', sex: '' }); }); }); data = alldata.concat(hutdata).concat(parkingdata).map(function(d) { // ★parkingdata追加 d.lat += (Math.random() - 0.5) * 0.0001; d.lng += (Math.random() - 0.5) * 0.0001; return d; }); initMap(); }) .catch(function(err){ console.error('Data loading error:', err); if(titleEl) titleEl.innerText = "データの読み込みに失敗しました"; }); } function initMap() { if (map) return; map = L.map('map-canvas').setView(currentArea.center, currentArea.zoom); L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png').addTo(map); layer = L.markerClusterGroup({ maxClusterRadius: 40, spiderfyOnMaxZoom: true }).addTo(map); var mountainLayer = L.layerGroup().addTo(map); var hutLayer = L.layerGroup().addTo(map); var parkingLayer = L.layerGroup().addTo(map); // ★追加 var gourmetLayer = L.layerGroup().addTo(map); var onsenLayer = L.layerGroup().addTo(map); window.filterMountain = function(cat) { window.activeMountainFilter = cat; var leg100 = document.getElementById('leg-100'); var leg200 = document.getElementById('leg-200'); var leg300 = document.getElementById('leg-300'); if(leg100) leg100.style.opacity = (cat === 'all' || cat === '百名山') ? '1' : '0.4'; if(leg200) leg200.style.opacity = (cat === 'all' || cat === '二百名山') ? '1' : '0.4'; if(leg300) leg300.style.opacity = (cat === 'all' || cat === '三百名山') ? '1' : '0.4'; update(); }; window.update = function() { layer.clearLayers(); mountainLayer.clearLayers(); hutLayer.clearLayers(); parkingLayer.clearLayers(); // ★追加 gourmetLayer.clearLayers(); onsenLayer.clearLayers(); var yV = document.getElementById('yearF').value, aV = document.getElementById('ageF').value, sV = document.getElementById('sexF').value, cV = document.getElementById('catF').value, stV = document.getElementById('statF').value; data.forEach(function(d) { var inArea = (d.lat >= currentArea.bounds.minLat && d.lat <= currentArea.bounds.maxLat && d.lng >= currentArea.bounds.minLng && d.lng <= currentArea.bounds.maxLng); var isMountain = (d.cat === '百名山' || d.cat === '二百名山' || d.cat === '三百名山'); var isHut = (d.cat === '山小屋'); var isParking = (d.cat === '駐車場'); // ★追加 var isGourmet = (d.cat === 'グルメ'); var isOnsen = (d.cat === '温泉'); // 山小屋は専用レイヤーで制御 if (inArea && isHut) { if (window.showHuts) { var hutIcon = L.divIcon({ html: '
🏠
', iconSize: [30, 30], iconAnchor: [15, 15] }); var hutPopup = '' + d.title + '
'; hutPopup += '
' + d.desc; hutPopup += '
'; hutPopup += '✍️ この情報を修正・追記'; hutPopup += '
'; L.marker([d.lat, d.lng], {icon: hutIcon}).bindPopup(hutPopup).addTo(hutLayer); } return; } // ★追加: 駐車場は専用レイヤーで制御 if (inArea && isParking) { if (window.showParking) { var parkingIcon = L.divIcon({ html: '
🅿
', iconSize: [30, 30], iconAnchor: [15, 15] }); var parkingPopup = '' + d.title + '
'; parkingPopup += '
' + d.desc; parkingPopup += '
'; parkingPopup += '✍️ この情報を修正・追記'; parkingPopup += '
'; L.marker([d.lat, d.lng], {icon: parkingIcon}).bindPopup(parkingPopup).addTo(parkingLayer); } return; } // グルメはデフォルトOFF・専用レイヤーで制御 if (inArea && isGourmet) { if (window.showGourmet) { var gourmetIcon = L.divIcon({ html: '
🍙
', iconSize: [30, 30], iconAnchor: [15, 15] }); var gourmetPopup = '' + d.title + '

' + d.desc.replace(/\n/g, '
'); if (d.taberogu_link) { gourmetPopup += '
🍴 食べログで口コミを見る
'; } gourmetPopup += '
✍️ この情報を修正・追記
'; L.marker([d.lat, d.lng], {icon: gourmetIcon}).bindPopup(gourmetPopup).addTo(gourmetLayer); } return; } // 温泉はデフォルトOFF・専用レイヤーで制御 if (inArea && isOnsen) { if (window.showOnsen) { var onsenIcon = L.divIcon({ html: '
♨️
', iconSize: [30, 30], iconAnchor: [15, 15] }); var onsenPopup = '' + d.title + '

' + d.desc.replace(/\n/g, '
'); onsenPopup += '
'; if (d.jalan_link) { onsenPopup += 'じゃらんで宿を探す'; } if (d.rakuten_link) { onsenPopup += '楽天トラベルで探す'; } onsenPopup += '
'; onsenPopup += '
✍️ この情報を修正・追記
'; L.marker([d.lat, d.lng], {icon: onsenIcon}).bindPopup(onsenPopup).addTo(onsenLayer); } return; } if (inArea && (yV === 'all' || String(d.year).includes(yV)) && (aV === 'all' || d.age.includes(aV)) && (sV === 'all' || d.sex === sV) && (cV === 'all' || d.cat.includes(cV)) && (stV === 'all' || d.stat === stV) && !(isMountain && window.activeMountainFilter !== 'all' && d.cat !== window.activeMountainFilter) ) { var cls = 'icon-alive', icon = '⚠️'; if (d.stat === '死亡') { cls = 'icon-dead'; icon = '💀'; } else if (d.cat === '伝承') { cls = 'icon-folklore'; icon = '⛩️'; } else if (d.cat === 'グルメ') { cls = 'icon-gourmet'; icon = '🍙'; } else if (d.cat === '温泉') { cls = 'icon-onsen'; icon = '♨️'; } else if (d.cat === '百名山') { cls = 'icon-mountain'; icon = '⛰️'; } else if (d.cat === '二百名山') { cls = 'icon-mountain200'; icon = '⛰️'; } else if (d.cat === '三百名山') { cls = 'icon-mountain300'; icon = '⛰️'; } var divIcon = L.divIcon({ html: '
' + icon + '
', iconSize: [30, 30], iconAnchor: [15, 15] }); var popup = '' + d.title + '
'; if (d.cat === 'グルメ' || d.cat === '伝承' || d.cat === '温泉' || isMountain) { popup += '
' + d.desc.replace(/\n/g, '
'); if (isMountain) { var isC = MountainChecklist.isClimbed(d.title); var safeTitle = d.title.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); popup += ''; popup += '
' + '' + '📄 ' + d.title + 'の詳細ページを見る
'; } } else { popup += d.year + '年 / ' + d.age + d.sex + '
状態:' + d.stat + '
' + d.desc.replace(/\n/g, '
'); } if (d.cat === '温泉') { popup += '
'; if (d.jalan_link) { popup += 'じゃらんで宿を探す'; } if (d.rakuten_link) { popup += '楽天トラベルで探す'; } popup += '
'; } if (d.cat === 'グルメ' && d.taberogu_link) { popup += '
'; popup += '🍴 食べログで口コミを見る'; popup += '
'; } if (d.link) { popup += '
参考リンクを見る'; } popup += '
'; popup += '✍️ この情報を修正・追記'; popup += '
'; var marker = L.marker([d.lat, d.lng], {icon: divIcon}).bindPopup(popup); if (isMountain) { marker.addTo(mountainLayer); } else { marker.addTo(layer); } } }); MountainChecklist.updateBar(data); }; update(); function setupMountainWarp() { var datalist = document.getElementById('mountainList'); if (!datalist) return; var mountains = data.filter(function(d) { return (d.cat === '百名山' || d.cat === '二百名山' || d.cat === '三百名山') && d.lat >= currentArea.bounds.minLat && d.lat <= currentArea.bounds.maxLat && d.lng >= currentArea.bounds.minLng && d.lng <= currentArea.bounds.maxLng; }); mountains.sort(function(a, b) { return b.lat - a.lat; }); mountains.forEach(function(m) { var opt = document.createElement('option'); opt.value = m.title; opt.dataset.lat = m.lat; opt.dataset.lng = m.lng; datalist.appendChild(opt); }); } window.warpToMountain = function() { var inputVal = document.getElementById('mountainSearch').value; if (!inputVal) return; var datalist = document.getElementById('mountainList'); var options = datalist.options; for (var i = 0; i < options.length; i++) { if (options[i].value === inputVal) { map.flyTo([parseFloat(options[i].dataset.lat), parseFloat(options[i].dataset.lng)], 11); return; } } }; setupMountainWarp(); } loadData(); var zoomLat = urlParams.get('lat'); var zoomLng = urlParams.get('lng'); if (zoomLat && zoomLng) { setTimeout(function() { map.flyTo([parseFloat(zoomLat), parseFloat(zoomLng)], 13); }, 1500); } });