// URLからパラメータを取得する関数
function getUrlParameter(name) {
const params = new URLSearchParams(window.location.search);
return params.get(name);
}
// チートモードかどうかを確認
const isCheatMode = getUrlParameter('cheat') !== null;
var mymap = L.map('mymap', {
zoomControl: false, // ズームコントロールを無効化してレンダリングを減らす
}).setView([38.891, 139.824], 16);
L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
attribution: '<a href="http://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
updateWhenIdle: true, // アイドル時のみタイルを更新
updateWhenZooming: false // ズーム中はタイルを更新しない
}).addTo(mymap);
function latlngdist(pos1, pos2) {
return pos1.distanceTo(pos2);
}
var path = [];
var line = null;
var lineprop = {
color: 'navy', opacity: 0.6, weight: 8
};
var sMarker, gMarker;
var totalDist = 0;
var info = document.getElementById('info');
var congratulationShown = false;
// 地点追加ボタンの参照を取得
var addPointButton = document.getElementById('addPoint');
function saveMeasurement(distance) {
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD形式
let measurements = JSON.parse(localStorage.getItem('measurements')) || {};
if (measurements[today]) {
measurements[today] += distance;
} else {
measurements[today] = distance;
}
localStorage.setItem('measurements', JSON.stringify(measurements));
}
function displayTotalDistance() {
const measurements = JSON.parse(localStorage.getItem('measurements')) || {};
let totalDistance = 0;
let history = '';
for (const [date, distance] of Object.entries(measurements)) {
totalDistance += distance;
history += `${date}: ${Math.round(distance * 100) / 100}m\n`;
}
info.innerHTML = `総距離: ${Math.round(totalDistance * 100) / 100}m\n\n履歴:\n${history}`;
}
function updatedistance(delta) {
totalDist += delta;
var roundedDist = Math.round(totalDist * 100) / 100;
if (roundedDist >= 2000 && !congratulationShown) {
info.innerHTML = 'おつかれさま! 距離: ' + roundedDist + 'm';
congratulationShown = true;
} else {
info.innerHTML = '距離: ' + roundedDist + 'm';
}
}
function finishMeasurement() {
// 測定を終了し、新たな測定を防ぐ
mymap.off('click', measurePath);
if (!isCheatMode) {
mymap.off('locationfound', onLocationFound);
mymap.stopLocate();
}
// 完了を視覚的に示す
if (line) {
line.setStyle({color: 'green', weight: 10});
}
saveMeasurement(totalDist);
displayTotalDistance();
resetPath();
}
function resetPath() {
if (sMarker) sMarker.remove(mymap);
if (gMarker) gMarker.remove(mymap);
if (line) line.remove(mymap);
line = sMarker = gMarker = null;
path = [];
totalDist = 0;
congratulationShown = false;
mymap.doubleClickZoom.enable();
info.innerHTML = 'クリアしました';
// イベントリスナーを再設定
if (isCheatMode) {
mymap.on('click', measurePath);
} else {
mymap.on('locationfound', onLocationFound);
mymap.locate({watch: true, enableHighAccuracy: true});
}
}
function throttle(func, limit) {
let lastFunc;
let lastRan;
return function() {
const context = this;
const args = arguments;
if (!lastRan) {
func.apply(context, args);
lastRan = Date.now();
} else {
clearTimeout(lastFunc);
lastFunc = setTimeout(function() {
if ((Date.now() - lastRan) >= limit) {
func.apply(context, args);
lastRan = Date.now();
}
}, limit - (Date.now() - lastRan));
}
}
}
function addPointToPath(latlng) {
var imsg = '北緯 ' + latlng.lat + ' 東経 ' + latlng.lng;
mymap.doubleClickZoom.disable();
if (path.length > 1 && latlng.equals(path[path.length-1])) {
return null;
}
path.push(latlng);
if (path.length == 1) {
sMarker = L.marker(path[0]).addTo(mymap).bindPopup(imsg);
gMarker = L.marker(path[0]).addTo(mymap).bindPopup(imsg);
line = L.polyline(path, lineprop).addTo(mymap);
info.innerHTML = imsg;
} else {
line.addLatLng(latlng);
gMarker.setLatLng(latlng);
}
if (path.length > 1) {
updatedistance(latlngdist(path[path.length-2], path[path.length-1]));
}
}
var measurePath = throttle(function(e) {
var latlng = e.latlng;
addPointToPath(latlng);
if (e.originalEvent && e.originalEvent.shiftKey) {
resetPath(e);
}
}, 300);
function removePoint(e) {
if (path.length > 1) {
let rm = path.pop();
updatedistance(-latlngdist(rm, path[path.length-1]));
line.setLatLngs(path);
gMarker.setLatLng(path[path.length-1]);
mymap.panTo(path[path.length-1]);
} else {
info.innerHTML = '始点は削れません。'
}
}
// チートモードの確認と地点追加ボタンの表示/非表示の設定
if (isCheatMode) {
mymap.on('click', measurePath);
addPointButton.style.display = 'none';
} else {
addPointButton.style.display = 'inline-block';
// 地点追加ボタンのイベントリスナー
addPointButton.addEventListener('click', function() {
mymap.locate({setView: true, maxZoom: 16});
});
// 位置情報取得成功時の処理
function onLocationFound(e) {
addPointToPath(e.latlng);
}
mymap.on('locationfound', onLocationFound);
// 位置情報取得失敗時の処理
mymap.on('locationerror', function(e) {
alert("位置情報を取得できませんでした: " + e.message);
});
// 初期位置取得
mymap.locate({setView: true, maxZoom: 16});
}
mymap.on('contextmenu', removePoint);
document.getElementById('undo').addEventListener('click', removePoint);
document.getElementById('finish').addEventListener('click', finishMeasurement);
// 初期表示時に総距離を表示
displayTotalDistance();