From 740736e69e59c2f2e5c6993ec64c9561e7191020 Mon Sep 17 00:00:00 2001 From: Miyadaj Date: Fri, 15 Nov 2024 12:28:49 +0900 Subject: [PATCH] modified functions --- assets/style.css | 1 + index.html | 4 +- js/conv.js | 47 +++++---- js/main.js | 256 ++++++++++++++++++++++++++--------------------- 4 files changed, 168 insertions(+), 140 deletions(-) diff --git a/assets/style.css b/assets/style.css index 0281393..15ca592 100644 --- a/assets/style.css +++ b/assets/style.css @@ -62,6 +62,7 @@ button, select { background-color: white; color: black; padding: 0 10px; + border: solid; border-width: thin; border-radius: 4px; font-size: 16px; diff --git a/index.html b/index.html index dc445ef..d2bfa4b 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - + @@ -11,9 +11,9 @@ 大札幌座標系 + - diff --git a/js/conv.js b/js/conv.js index 73610eb..8e510a1 100644 --- a/js/conv.js +++ b/js/conv.js @@ -2,7 +2,7 @@ const hgsSet = { Sapporo: { name: "大札幌 座標系", format: [["北", "南", "大通"], ["東", "西"]], - jo: "latitudinal", + joOffset: ["latitudinal", 175, 110], origin: [43.061138, 141.357079], declination: 10.5842138889, blockSizeLatLng: [0.001170046801872075, 0.0011661354271942782], @@ -11,7 +11,7 @@ const hgsSet = { Obihiro: { name: "帯広 座標系", format: [["西", "東", "大通"], ["南", "北"]], - jo: "longitudinal", + joOffset: ["longitudinal", 69, 69], origin: [42.932044, 143.204010], declination: 5.59292777778, blockSizeLatLng: [0.001170168504264614, 0.0011660447761194029], @@ -20,7 +20,7 @@ const hgsSet = { Nayoro: { name: "名寄 座標系", format: [["西", "東", "大通"], ["南", "北"]], - jo: "longitudinal", + joOffset: ["longitudinal", 74, 74], origin: [44.356392, 142.463787], declination: 0.0992, blockSizeLatLng: [0.001169909916936396, 0.0011659012740710033], @@ -29,7 +29,7 @@ const hgsSet = { Nakashibetsu: { name: "中標津 座標系", format: [["東", "西", "大通"], ["南", "北"]], - jo: "longitudinal", + joOffset: ["longitudinal", 45.5, 45.5], origin: [43.548025, 144.973040], declination: 42.1626611111, blockSizeLatLng: [0.0008177655011993894, 0.0008174683912222061], @@ -48,8 +48,6 @@ const hgsSet = { Shibetsu: {}, */ }; -let format, blockPosition; -let coordinateSystem = "Sapporo"; Decimal.set({ precision: 30, @@ -75,24 +73,29 @@ const pi = acos(-1); const radians = (deg) => Decimal.div(pi, 180).mul(deg); const degrees = (rad) => Decimal.div(180, pi).mul(rad); +let latLng = []; +let blockPosition = []; +let jochome = []; +let coordinateSystem = "Sapporo"; + let originLat = radians(hgsSet[coordinateSystem].origin[0]); let originLat1 = atan(sub(1, e2).mul(tan(originLat))) let originLng = radians(hgsSet[coordinateSystem].origin[1]); let dec = radians(hgsSet[coordinateSystem].declination) //wgs84の経緯度をhgsの経緯度に変換 -function wgs2hgs(lat, lng) { +function wgs2hgs([lat, lng]) { const latRad = radians(lat); const lngRad = radians(lng); //地点(lat, lng)を指すベクトルをHGSに変換: (X, Y, Z) - const f = (phi, delta) => { + const g = (phi, delta) => { const a = sub(1, e2).mul(cos(phi)).mul(cos(delta)).mul(sin(latRad)); const b = cos(latRad).mul(sin(delta).mul(sin(lngRad.sub(originLng))).add(sin(phi).mul(cos(delta)).mul(cos(lngRad.sub(originLng))))); return sub(a, b) }; - const X = f(originLat1.sub(pi.div(2)), 0) - const Y = f(originLat1, dec.sub(pi.div(2))) - const Z = f(originLat1, dec) + const X = g(originLat1.sub(pi.div(2)), 0) + const Y = g(originLat1, dec.sub(pi.div(2))) + const Z = g(originLat1, dec) let LAT = degrees(asin(Z.div(sqrt(sin(latRad).pow(2).mul(e2.pow(2).sub(e2.mul(2))).add(1))))); let LNG = degrees(atan2(Y, X)); @@ -102,7 +105,7 @@ function wgs2hgs(lat, lng) { }; //hgsの経緯度をwgsの経緯度に変換 -function hgs2wgs(LAT, LNG) { +function hgs2wgs([LAT, LNG]) { const LATRad = radians(LAT); const LNGRad = radians(LNG); //HGS上の地点(LAT, LNG)を指す単位ベクトルをWGSに変換: (nx, ny, nz) @@ -123,19 +126,19 @@ function hgs2wgs(LAT, LNG) { return [lat, lng] }; -//HGS経緯度から条丁目を算出 -function getBlockPosition(LATLNG) { - let latitudinalBlock = Decimal.abs(LATLNG[0]).div(hgsSet[coordinateSystem].blockSizeLatLng[0]).floor(); - let longitudinalBlock = Decimal.abs(LATLNG[1]).div(hgsSet[coordinateSystem].blockSizeLatLng[1]).floor(); - latitudinalBlock = Decimal(Math.sign(LATLNG[0])).mul(latitudinalBlock); - longitudinalBlock = Decimal(Math.sign(LATLNG[1])).mul(longitudinalBlock); +//HGS経緯度から区画の位置を算出 +function hgs2blockPosition([LAT, LNG]) { + let latitudinalBlock = Decimal.abs(LAT).div(hgsSet[coordinateSystem].blockSizeLatLng[0]).floor().add(1); + let longitudinalBlock = Decimal.abs(LNG).div(hgsSet[coordinateSystem].blockSizeLatLng[1]).floor().add(1); + latitudinalBlock = Decimal(Math.sign(LAT)).mul(latitudinalBlock); + longitudinalBlock = Decimal(Math.sign(LNG)).mul(longitudinalBlock); blockPosition = [latitudinalBlock, longitudinalBlock] return blockPosition; }; -//条丁目からHGS経緯度を算出 -function getLatLng(latLngBlock) { - const LAT = new Decimal(latLngBlock[0]).sub(1).mul(hgsSet[coordinateSystem].blockSizeLatLng[0]); - const LNG = new Decimal(latLngBlock[1]).sub(1).mul(hgsSet[coordinateSystem].blockSizeLatLng[1]); +//区画の位置からHGS経緯度を算出 +function blockPosition2hgs([latitudinalBlock, longitudinalBlock]) { + const LAT = new Decimal(latitudinalBlock).mul(hgsSet[coordinateSystem].blockSizeLatLng[0]); + const LNG = new Decimal(longitudinalBlock).mul(hgsSet[coordinateSystem].blockSizeLatLng[1]); return [LAT, LNG] }; \ No newline at end of file diff --git a/js/main.js b/js/main.js index 47c27de..95354d1 100644 --- a/js/main.js +++ b/js/main.js @@ -1,3 +1,5 @@ +const inputLatLngElement = document.getElementById("latLng"); +const divJochomeElement = document.getElementById("jochome"); //座標系のリスト作成 const selectSystemElement = document.getElementById("selectCoordinateSystem"); Object.keys(hgsSet).forEach(key => { @@ -8,64 +10,135 @@ Object.keys(hgsSet).forEach(key => { }); //初期表示 -let map, marker; -let inputLatLng, latLngArray; +let map, marker, redMarker; +let origin, zoom; createMap(coordinateSystem); createFormatJochome(coordinateSystem); updateJochome(); -setSystemFromURL(); + +//イベントリスナー +selectSystemElement.addEventListener("change", () => { + updateCoordinateSystem(); + createMap(coordinateSystem); + updateJochome(); +}); +inputLatLngElement.addEventListener("change", () => { + updateMarkerPosition(); + updateJochome(); + updateURL(); +}); +divJochomeElement.addEventListener("change", () => { + updateLatLngByJochome(); + updateMarkerPosition(); + updateURL(); +}); + +//地図表示関数 +function createMap(selectedSystem) { + if (!map) { + origin = hgsSet[selectedSystem].origin; + const twintown = hgsSet[selectedSystem].twintown; + map = L.map("map", { + minZoom: 2, + maxZoom: 18, + maxBounds: [ + [-90, -200], + [90, 200] + ], + }); + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + attribution: '© OpenStreetMap', + }).addTo(map); + // 原点を赤丸で表示 + redMarker = L.circleMarker(origin, { + color: "red", + fillColor: "red", + fillOpacity: 1, + radius: 5 + }).addTo(map); + // マーカーの初期位置を姉妹都市に + marker = L.marker(twintown, { draggable: true }).addTo(map); + // 初期位置をフィールドに表示 + document.getElementById("latLng").value = twintown.join(", "); + map.fitBounds([origin, twintown]); + setParamsFromURL(); + marker.on("dragend", function(e) { + const newLatLng = e.target.getLatLng(); + //マーカーの位置を制限 + const lat = Math.max(Math.min(newLatLng.lat, 90), -90); + const lng = Math.max(Math.min(newLatLng.lng, 180), -180); + //経緯度を更新 + inputLatLngElement.value = `${lat}, ${lng}`; + marker.setLatLng([lat, lng]) + map.setView([lat, lng]); + updateJochome(); + updateURL(); + }); + map.on("zoomend", updateURL) + } else { + redMarker.setLatLng(origin); + marker.setLatLng(latLng); + map.setView(latLng); + map.setZoom(zoom); + } +}; //座標系の更新 -selectSystemElement.addEventListener("change", function() { +function updateCoordinateSystem() { //変数の更新 coordinateSystem = selectSystemElement.value - originLat = radians(hgsSet[coordinateSystem].origin[0]); + origin = hgsSet[coordinateSystem].origin + originLat = radians(origin[0]); originLat1 = atan(sub(1, e2).mul(tan(originLat))) - originLng = radians(hgsSet[coordinateSystem].origin[1]); + originLng = radians(origin[1]); dec = radians(hgsSet[coordinateSystem].declination) + zoom = map.getZoom() //表示更新 + map.remove(); + map = null; createMap(coordinateSystem); createFormatJochome(coordinateSystem); const optionToRemove = document.getElementById("initialOption") if (optionToRemove) { optionToRemove.remove() }; - updateURL(); -}); - -// 緯度と経度の入力フィールドにイベントリスナーを追加 -document.getElementById("latLng").addEventListener("change", updateMarkerPosition); -document.getElementById("latLng").addEventListener("change", updateJochome); -document.getElementById("latLng").addEventListener("change", updateURL); -document.getElementById("jochome").addEventListener("change", updateLatLngByJochome); - +}; //urlクエリパラメータを代入 -function setInputFromURL() { +function setParamsFromURL() { const urlParams = new URLSearchParams(window.location.search); const lat = urlParams.get('lat'); const lng = urlParams.get('lng'); - if (lat && lng) { - latLngArray = [lat, lng] - document.getElementById('latLng').value = `${lat}, ${lng}`; - document.getElementById("latLng").dispatchEvent(new Event("change")); - } -}; - -function setSystemFromURL() { - const urlParams = new URLSearchParams(window.location.search); - coordinateSystem = urlParams.get('coordinateSystem') - if (coordinateSystem) { - selectSystemElement.value = coordinateSystem + const z = urlParams.get('z'); + const sys = urlParams.get('sys'); + const sys2 = urlParams.get('coordinateSystem'); + if (!(lat || lng || z)) + return; + if (!sys || !sys2) + return; + latLng = [lat, lng]; + zoom = z; + marker.setLatLng(latLng); + map.setView(latLng, zoom ? zoom : 6); + document.getElementById('latLng').value = `${lat}, ${lng}`; + if (sys) { + selectSystemElement.value = sys + updateCoordinateSystem(); + } else if (sys2) { + selectSystemElement.value = sys2 + updateCoordinateSystem(); }; }; function updateURL() { updateLatLng() - const lat = latLngArray[0]; - const lng = latLngArray[1]; const newUrl = new URL(window.location.href); - coordinateSystem = selectSystemElement.value - newUrl.searchParams.set('coordinateSystem', coordinateSystem); + const lat = latLng[0]; + const lng = latLng[1]; + const zoom = map.getZoom(); + const currentSystem = selectSystemElement.value + if (currentSystem) { + newUrl.searchParams.set('sys', currentSystem); + } if (lat && lng) { newUrl.searchParams.set('lat', lat); newUrl.searchParams.set('lng', lng); @@ -73,8 +146,11 @@ function updateURL() { newUrl.searchParams.delete('lat'); newUrl.searchParams.delete('lng'); } + if (zoom) { + newUrl.searchParams.set('z', zoom) + } history.pushState(null, '', newUrl); -} +}; //条丁目の形式を表示 function createFormatJochome(selectedSystem) { @@ -108,53 +184,6 @@ function deleteOptionJochome() { }); }; -//地図表示関数 -function createMap(selectedSystem) { - if (map) { - map.remove(); - }; - const origin = hgsSet[selectedSystem].origin; - const twintown = hgsSet[selectedSystem].twintown; - map = L.map("map", { - center: origin, - zoom: 13, - maxBounds: [ - [-90, -200], - [90, 200] - ], - }); - const tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { - attribution: '© OpenStreetMap', - }); - tileLayer.addTo(map); - - // 原点を赤丸で表示 - L.circleMarker(origin, { - color: "red", - fillColor: "red", - fillOpacity: 1, - radius: 5 - }).addTo(map); - // マーカーの初期位置を姉妹都市に - marker = L.marker(twintown, { draggable: true }).addTo(map); - // 初期位置をフィールドに表示 - document.getElementById("latLng").value = twintown.join(", "); - // マーカーをドラッグして緯度経度を更新する - marker.on("dragend", function(e) { - const newLatLng = e.target.getLatLng(); - //マーカーの位置を制限 - const lat = Math.max(Math.min(newLatLng.lat, 90), -90); - const lng = Math.max(Math.min(newLatLng.lng, 180), -180); - - const newCoordinate = [lat, lng] - const evt = new Event("change"); - document.getElementById("latLng").value = newCoordinate.join(", "); - document.getElementById("latLng").dispatchEvent(evt); - }); - map.fitBounds([origin, twintown]); -}; - - function updateLatLngByJochome() { const selectedText = (id) => { const selectElement = document.getElementById(id); @@ -168,50 +197,48 @@ function updateLatLngByJochome() { "南": -1, "大通": 0 }; - format[0] = selectedText("selectJo"); - format[1] = document.getElementById("joNumber").value - format[2] = selectedText("selectChome"); - format[3] = document.getElementById("chomeNumber").value - if (hgsSet[coordinateSystem].jo == "longitude") { - blockPosition[1] = dirSign[format[0]]*format[1]; - blockPosition[0] = dirSign[format[2]]*format[3]; + jochome[0] = selectedText("selectJo"); + jochome[1] = document.getElementById("joNumber").value + jochome[2] = selectedText("selectChome"); + jochome[3] = document.getElementById("chomeNumber").value + if (hgsSet[coordinateSystem].joOffset[0] == "longitudinal") { + blockPosition[1] = dirSign[jochome[0]]*jochome[1]; + blockPosition[0] = dirSign[jochome[2]]*jochome[3]; } else { - blockPosition[0] = dirSign[format[0]]*format[1]; - blockPosition[1] = dirSign[format[2]]*format[3]; + blockPosition[0] = dirSign[jochome[0]]*jochome[1]; + blockPosition[1] = dirSign[jochome[2]]*jochome[3]; } - const latLngHGS = getLatLng(blockPosition); - const latLng = hgs2wgs(latLngHGS[0], latLngHGS[1]) - const evt = new Event("change") + const latLngHGS = blockPosition2hgs(blockPosition); + latLng = hgs2wgs(latLngHGS) document.getElementById("latLng").value = latLng; - document.getElementById("latLng").dispatchEvent(evt); }; function updateJochome() { - const format = getJochome(); + jochome = getJochome(); const elementJoNumber = document.getElementById("joNumber"); const elementChomeNumber = document.getElementById("chomeNumber"); - if (format[0] === "大通") { + if (jochome[0] == "大通") { switchAppearanceJo("odori"); - selectOptionByText("selectJo", format[0]); - selectOptionByText("selectChome", format[2]); - elementChomeNumber.value = format[3]; + selectOptionByText("selectJo", jochome[0]); + selectOptionByText("selectChome", jochome[2]); + elementChomeNumber.value = jochome[3]; } else { switchAppearanceJo("directional"); - selectOptionByText("selectJo", format[0]); - elementJoNumber.value = format[1]; - selectOptionByText("selectChome", format[2]); - elementChomeNumber.value = format[3]; + selectOptionByText("selectJo", jochome[0]); + elementJoNumber.value = jochome[1]; + selectOptionByText("selectChome", jochome[2]); + elementChomeNumber.value = jochome[3]; } }; function getJochome() { updateLatLng() - const hgsCoordinates = wgs2hgs(latLngArray[0], latLngArray[1]); //see conv.js - const blockPosition = getBlockPosition(hgsCoordinates); + const hgsCoordinates = wgs2hgs(latLng); //see conv.js + const blockPosition = hgs2blockPosition(hgsCoordinates); let jo, chome, eastWest, northSouth; - if (hgsSet[coordinateSystem].jo === "longitudinal") { + if (hgsSet[coordinateSystem].joOffset[0] == "longitudinal") { jo = blockPosition[1]; chome = blockPosition[0]; northSouth = chome > 0 ? "北" : "南"; @@ -226,7 +253,7 @@ function getJochome() { eastWest = "大通" break }; - format = [eastWest, Math.abs(jo), northSouth, Math.abs(chome)]; + jochome = [eastWest, Math.abs(jo), northSouth, Math.abs(chome)]; } else { jo = blockPosition[0]; @@ -243,17 +270,16 @@ function getJochome() { northSouth = "大通" break }; - format = [northSouth, Math.abs(jo), eastWest, Math.abs(chome)]; + jochome = [northSouth, Math.abs(jo), eastWest, Math.abs(chome)]; }; - return format; + return jochome; }; function updateMarkerPosition() { updateLatLng() - const newLat = parseFloat(latLngArray[0]); - const newLng = parseFloat(latLngArray[1]); + const newLat = parseFloat(latLng[0]); + const newLng = parseFloat(latLng[1]); if (!isNaN(newLat) && !isNaN(newLng)) { - // マーカーがすでに存在する場合のみ更新 if (marker) { marker.setLatLng([newLat, newLng]); map.setView([newLat, newLng]); // 地図の表示位置も合わせて移動 @@ -289,8 +315,6 @@ function selectOptionByText(id, text) { }; }; function updateLatLng() { - inputLatLng = document.getElementById("latLng").value; - latLngArray = inputLatLng.split(",").map(item => parseFloat(item.trim())) -}; - -setInputFromURL(); \ No newline at end of file + const inputLatLng = document.getElementById("latLng").value; + latLng = inputLatLng.split(",").map(item => parseFloat(item.trim())) +}; \ No newline at end of file