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