Newer
Older
JAXAtools / THG / thg.js
@HIROSE Yuuji HIROSE Yuuji on 22 Oct 2024 6 KB Adjust goals
document.addEventListener("DOMContentLoaded", ()=>{
    const DEBUG = document.URL.match(/debug/);
    const G_KETA = 6, LSkey = "markers";
    const POND = [38.892143, 139.824226], DOLL = [38.89226, 139.819763];
    const goals = {pond: POND, doll: DOLL};
    const points = {
	"ルビー":	[38.895249, 139.822126],
	//"サファイヤ":	[38.889365, 139.821872],
	"サファイヤ":	[38.889387, 139.821946],
	"アメジスト":	[38.929598, 139.852712]
    };
    const thresh = 30.0;
    var gnssWatchID = null, gnssCount = {};
    var mymap, infobox, btnGet, btnSTOP;
    var yellowIcon;
    var gsiLayer = L.tileLayer(
	'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
	    attribution:
	    '<a href="http://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
	    maxZoom: 20, maxNativeZoom: 18
	});
    var gsiPhoto = L.tileLayer(
	'https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg',
	{attribution: '&copy; <a href="http://maps.gsi.go.jp/development/ichiran.html">国土地理院</a>',
	 maxZoom: 20, maxNativeZoom: 18});
    var osmLayer = L.tileLayer(
	'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
	    attribution:
	    '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
	    maxZoom: 20, maxNativeZoom: 18
	});
    var offlineLayerGsiPhoto = L.imageOverlay(
	"img/koekimap.png",
	[[38.895917, 139.816078], [38.888749, 139.826029]]
    );
    var offlineLayerOSM = L.imageOverlay(
	"img/osm-koekimap.png",
	[[38.895917, 139.816078], [38.888749, 139.826029]]
    );
    var baseLayers = {
	"(オフライン用)大学周辺地理院空中写真": offlineLayerGsiPhoto,
	"(オフライン用)大学周辺OSM": offlineLayerOSM,
	OpenStreetMap: osmLayer,
	地理院地図: gsiLayer,
	地理院空中写真: gsiPhoto,
    };
    function workerInit() {
	if ('serviceWorker' in navigator) {
	    navigator.serviceWorker.register('./serviceworker.js')
		.then(function() {
		    console.log('service worker registered');
		});
	}
    }
    var stoPrefix = "thg_";
    var LS = {
	"getItem": (i)=>{return localStorage.getItem(stoPrefix+i);},
	"removeItem": (i)=>{return localStorage.removeItem(stoPrefix+i);},
	"setItem": (k,v)=>{return localStorage.setItem(stoPrefix+k, v);},
	"reset": ()=>{
	    for (let p of Object.keys(localStorage)) {
		console.log(`LS=${p}`);
		if (p.startsWith(stoPrefix))
		    localStorage.removeItem(p);
	    }
	}
    }
    function mvMarker(ll) {
	let info = `北緯=${ll.lat.toFixed(G_KETA)}
東経=${ll.lng.toFixed(G_KETA)}`;
	let dist;
	let div = document.createElement("div"),
	    p   = document.createElement("p");
	lastMarker.setLatLng(ll);
	// Search nearest point and show distance
	let distList = [];
	for (let p in points) {
	    distList.push({name: p, dist: ll.distanceTo(points[p])});
	}
	distList = distList.sort((a,b) => {
	    if (a.dist < b.dist) return -1;
	    if (a.dist > b.dist) return 1;
	    return 0;
	});
	let d = distList[0].dist.toFixed(1);
	if (d/1.0 > thresh) {
	    dispInfo(`一番近い石まで${d}m`);
	    return;
	}
	let here = distList[0].name, herell;
	let stonePos = L.latLng(points[here]);
	if (DEBUG)
	    herell = ll;
	else
	    herell = stonePos;
	dispInfo(`ここは${here}. 賢者への司令はマーカーに記した。タップせよ。`);
	let s = `宝のありかまで`;
	if (DEBUG) {
	    for (let target in goals) {
		dist = herell.distanceTo(goals[target]).toFixed(1);
		s += ", "+target.toString()+"="+dist+`\n`;
	    }
	}
	dist = stonePos.distanceTo(goals.doll).toFixed(1);
	s += `あと${dist}m
ここから${dist}mの地点をくまなく調べるのじゃ。

(この場所をしっかり記録して教室にもどって地図で探そう!)`;
	/*
	if (ll.distanceTo(stonePos) > 5) {
	    L.marker(stonePos, {icon: yellowIcon}).addTo(mymap);
	    }
	*/
	p.innerText = s;
	div.appendChild(p);
	//div.appendChild(btn);
	
	console.log(`s=${s}`);
	lastMarker.bindPopup(div);
	lastMarker.on('popupopen', (e)=>{
	    let p = e.target.getPopup().getContent().querySelector("p");
	    popupOpenedMarker = e.target;
	});
	lastMarker.addTo(mymap).openPopup();
    }
    function mvMarkerByGNSS(latlng) {
	mymap.panTo(latlng);
	mvMarker(latlng);
    }
    function mvMarkerByClick(e) {
	mvMarker(e.latlng);
    }
    function mapInit() {
	infobox = document.getElementById("info");
	mymap = L.map("mymap", baseLayers).setView([38.894, 139.81976], 18);
	L.control.scale().addTo(mymap); // 縮尺表示追加
	lastMarker = L.marker(mymap.getCenter());
	lastMarker.setPopupContent("Hi!").addTo(mymap);
	btnGet  = document.getElementById("get");
	btnSTOP = document.getElementById("stop");
	if (btnGet) btnGet.addEventListener("click", getGNSS, false);
	if (btnSTOP)btnSTOP.addEventListener("click", stopGNSS, false);
	// Create yellow Icon
	yellowIcon = L.icon({
	    iconUrl:	"img/Yellow.png",
	    iconSize:	[40, 41],
	    iconAnchor:	[10, 41],
	    popupAnchor: [3, -41]
	});
	L.control.layers(baseLayers).addTo(mymap);
	// offlineLayerGsiPhoto.addTo(mymap);
	osmLayer.addTo(mymap);
	if (DEBUG) mymap.on('click', mvMarkerByClick);
    }
    function dispInfo(msg) {
	info.innerText = msg;
    }
    function clearWatchGNSS() {	// 位置取得ボタンを元に戻す
	mymap.stopLocate();
	gnssWatchID = null;
	btnGet.classList.remove('running');
	btnGet.disabled = false;
	// dispInfo("衛星信号取得停止");
    }
    function getGNSS(ev) {
	if (gnssWatchID) {
	    dispInfo("もう探索中なの、急かしても無駄よ.");
	    return;
	}
	gnssWatchID = mymap.locate({
	    watch:	false,
	    maximumAge: 0, timeout: 8000, enableHighAccuracy: true
	    });
	mymap.on('locationfound', onSuccess)
	mymap.on('locationerror', onError)
	btnGet.classList.add('running');
	btnGet.disabled = true;
	dispInfo("取得中...");
    }
    function stopGNSS(ev) {
	clearWatchGNSS();
	dispInfo("衛星信号捕捉を停止しました.");
    }
    function onSuccess(pos) { // 成功時のコールバック。関数名は何でもよい。
	// pos.coords に位置情報が入る。LeafletのLatLngに変換する。
	//onSuccessL(L.latLng([pos.coords.latitude, pos.coords.longitude]));
	console.log(pos.latlng);
	mvMarkerByGNSS(pos.latlng);
	clearWatchGNSS();
    }
    function onError(err) {// 失敗時のコールバック
	lastMarker.setPopupContent("取得失敗:").openPopup();
	dispInfo("空がよく見える位置でないと駄目なのよ");
	dispInfo("衛星信号捕捉は中止するわね.")
	clearWatchGNSS();
    }
    workerInit();
    mapInit();
});