From 51af495b9ff14f5be33f8251408824f618f109a2 Mon Sep 17 00:00:00 2001 From: WANG Lei Date: Thu, 7 May 2026 13:20:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8A=A8=E6=80=81=E5=A2=9E?= =?UTF-8?q?=E5=88=A0=E5=A4=A9=E4=BD=93=E8=BE=93=E5=85=A5=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pnpm-lock.yaml | 10 +- src/css/site.css | 124 +++++++- src/index.html | 112 +++---- src/interface/classes/interact.js | 23 ++ src/interface/elements/CelestialBody.js | 343 +++++++++++++-------- src/interface/functions/AutoComplete.js | 19 +- src/interface/functions/CeleRecognition.js | 34 +- src/interface/functions/PickCele.js | 4 - src/interface/init.js | 9 +- src/interface/utils.js | 67 +++- 10 files changed, 502 insertions(+), 243 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25a328e..f7a4fe4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -511,8 +511,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001676: - resolution: {integrity: sha512-Qz6zwGCiPghQXGJvgQAem79esjitvJ+CxSbSQkW9H/UX5hg8XM88d4lp2W+MEQ81j+Hip58Il+jGVdazk1z9cw==} + caniuse-lite@1.0.30001792: + resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==} canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -2947,7 +2947,7 @@ snapshots: browserslist@4.24.2: dependencies: - caniuse-lite: 1.0.30001676 + caniuse-lite: 1.0.30001792 electron-to-chromium: 1.5.49 node-releases: 2.0.18 update-browserslist-db: 1.1.1(browserslist@4.24.2) @@ -2978,11 +2978,11 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.24.2 - caniuse-lite: 1.0.30001676 + caniuse-lite: 1.0.30001792 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001676: {} + caniuse-lite@1.0.30001792: {} canvas@2.11.2: dependencies: diff --git a/src/css/site.css b/src/css/site.css index f74fb24..f48fcc8 100644 --- a/src/css/site.css +++ b/src/css/site.css @@ -18,6 +18,31 @@ td:hover { background-color: #1d2430; } +.inputTable .col-seq { + width: 5%; +} + +.inputTable .col-name { + width: 17%; +} + +.inputTable .col-hour-angle { + width: 23%; +} + +.inputTable .col-declination { + width: 18%; +} + +.inputTable .col-x, +.inputTable .col-y { + width: 13%; +} + +.inputTable .col-action { + width: 10%; +} + h1 { font-size: 24px; padding-left: 5px; @@ -37,7 +62,7 @@ input.table { text-align: center; background-color: #1d2d46; border: 0px; - color: white + color: white; } input.table:hover { @@ -52,7 +77,7 @@ input[type=text] { text-align: center; background-color: #1d2d46; border: 0px; - color: white + color: white; } a:link { @@ -191,6 +216,48 @@ a:visited { outline-offset: -8px; } +.canvasInfoBar { + display: flex; + flex-direction: column; + gap: 2px; + min-height: 44px; + margin-bottom: 30px; +} + +.canvasMetaBar, +.canvasStatusBar { + display: flex; + align-items: flex-start; + gap: 12px; + min-width: 0; +} + +.canvasMetaBar { + justify-content: space-between; + width: 100%; +} + +.canvasStatusBar { + flex-wrap: wrap; +} + +#picInfo, +#canvasStatus, +#celeStatus { + min-height: 20px; +} + +#picInfo { + flex: 1; +} + +#cursorCrd { + flex: 0 0 150px; + min-height: 20px; + text-align: right; + white-space: nowrap; +} + .outputColumn { margin-top: 15px; margin-bottom: 15px; @@ -245,6 +312,39 @@ a:visited { background-color: #194837; } +.actionButton.is-disabled { + opacity: 0.45; + filter: grayscale(65%); +} + +.actionButton.is-disabled:hover { + background-color: #187C54; +} + +.tableActionButton, +.addCeleRowButton { + border: 1px solid #189c65; + border-radius: 4px; + background-color: #187C54; + color: white; + cursor: pointer; +} + +.tableActionButton { + padding: 2px 6px; + font-size: 12px; +} + +.tableActionButton:hover, +.addCeleRowButton:hover { + background-color: #189c65; +} + +.addCeleRowButton { + margin-top: 6px; + padding: 4px 12px; +} + .helpButton { color: white; border: 2px solid #2150B7; @@ -318,12 +418,26 @@ a:visited { width: 90%; } +.celesNameInput { + display: block; + box-sizing: border-box; + width: 90%; + margin: 0 auto; + padding: 2px 4px; +} + .formatedInput { display: flex; + align-items: center; + justify-content: center; + gap: 4px; + height: 100%; + white-space: nowrap; } .formatedInput div { - flex: 1; + min-width: 22px; + text-align: center; overflow: hidden; text-overflow: clip; white-space: nowrap; @@ -443,14 +557,14 @@ a:visited { -ms-flex: 0 0 90%; flex: 0 0 90%; max-width: 90%; - margin-left: -1px + margin-left: -1px; } .col-calcul { -ms-flex: 0 0 10%; flex: 0 0 10%; max-width: 10%; - margin: 0px + margin: 0px; } .col-acknow { diff --git a/src/index.html b/src/index.html index 952ef1e..daf7932 100644 --- a/src/index.html +++ b/src/index.html @@ -78,25 +78,40 @@

测量

-
-
-
-
+
+
+
+
+
+
+
+
+
+ + + + + + + + + - - + - - - - + + + @@ -107,11 +122,12 @@

测量

+ + + - - - - - - - - - - - - - - - - +
序号天体的序号天体名称序号天体的序号天体名称天体的名称,中英文皆可;中文在星座名和希腊字母之间需要加上空格参考时角参考时角在0°经线读取的天体时角,可以用于计算GP点经度赤纬天体的赤纬,即GP点的纬度 + 赤纬天体的赤纬,即GP点的纬度 x天体在照片中的横坐标y天体在照片中的纵坐标x天体在照片中的横坐标y天体在照片中的纵坐标操作添加或删除天体行
0 N/A
1 - @@ -136,11 +152,12 @@

测量

2 - @@ -165,11 +182,12 @@

测量

3 - @@ -194,66 +212,10 @@

测量

4 - - -
-
- h -
- m -
- s -
-
-
-
- ° -
- ′ -
- ″ -
-
5 - - -
-
- h -
- m -
- s -
-
-
-
- ° -
- ′ -
- ″ -
-
+
+ `; + } + + bindTableRow(id) { + const name = document.getElementById(`name${id}`); + const coordX = document.getElementById(`coordX${id}`); + const coordY = document.getElementById(`coordY${id}`); + const removeButton = document.querySelector(`.removeCeleRow[data-star-id="${id}"]`); + + if (name) { + if (!name.dataset.autocompleteBound) { + autoCompleteStarName(name); + name.dataset.autocompleteBound = 'true'; + } + name.oninput = () => { + const star = this.array[id - 1]; + if (star) star.onRename(); + }; + name.onfocus = () => { + const star = this.array[id - 1]; + if (!star) return; + star.canvas.setActiveObject(star.point); + star.canvas.renderAll(); + }; + } + + const handleCoordInput = () => { + const x = parseFloat(coordX.value); + const y = parseFloat(coordY.value); + if (!Number.isFinite(x) || !Number.isFinite(y)) return; + coordX.dataset.rawValue = x; + coordY.dataset.rawValue = y; + + if (!this.interactPhoto.movable) { + this.interactPhoto.tips.innerHTML = '请先选择星空照片'; + return; + } + + if (id <= this.num()) { + this.array[id - 1].setRealXY(x, y); + this.array[id - 1].point.setCoords(); + this.array[id - 1].label.setCoords(); + this.interactPhoto.canvas.renderAll(); + return; + } + + if (id === this.num() + 1) { + this.add(x, y); + } else { + this.interactPhoto.tips.innerHTML = `请先填写第 ${this.num() + 1} 行的 x、y 坐标`; + } + }; + + if (coordX) coordX.oninput = handleCoordInput; + if (coordY) coordY.oninput = handleCoordInput; + if (removeButton) { + removeButton.onclick = () => { + this.removeTableRow(id); + }; + } + } + + clearTableRowData(id) { + document.getElementById(`name${id}`).value = ''; + document.getElementById(`hAngleH${id}`).textContent = ''; + document.getElementById(`hAngleM${id}`).textContent = ''; + document.getElementById(`hAngleS${id}`).textContent = ''; + delete document.getElementById(`hAngleS${id}`).dataset.rawValue; + document.getElementById(`declinD${id}`).textContent = ''; + document.getElementById(`declinM${id}`).textContent = ''; + document.getElementById(`declinS${id}`).textContent = ''; + delete document.getElementById(`declinS${id}`).dataset.rawValue; + document.getElementById(`coordX${id}`).value = ''; + document.getElementById(`coordY${id}`).value = ''; + delete document.getElementById(`coordX${id}`).dataset.rawValue; + delete document.getElementById(`coordY${id}`).dataset.rawValue; + } + + copyTableRowData(fromId, toId) { + document.getElementById(`name${toId}`).value = document.getElementById(`name${fromId}`).value; + document.getElementById(`hAngleH${toId}`).textContent = document.getElementById(`hAngleH${fromId}`).textContent; + document.getElementById(`hAngleM${toId}`).textContent = document.getElementById(`hAngleM${fromId}`).textContent; + document.getElementById(`hAngleS${toId}`).textContent = document.getElementById(`hAngleS${fromId}`).textContent; + document.getElementById(`declinD${toId}`).textContent = document.getElementById(`declinD${fromId}`).textContent; + document.getElementById(`declinM${toId}`).textContent = document.getElementById(`declinM${fromId}`).textContent; + document.getElementById(`declinS${toId}`).textContent = document.getElementById(`declinS${fromId}`).textContent; + document.getElementById(`coordX${toId}`).value = document.getElementById(`coordX${fromId}`).value; + document.getElementById(`coordY${toId}`).value = document.getElementById(`coordY${fromId}`).value; + this.copyRawValue(`hAngleS${fromId}`, `hAngleS${toId}`); + this.copyRawValue(`declinS${fromId}`, `declinS${toId}`); + this.copyRawValue(`coordX${fromId}`, `coordX${toId}`); + this.copyRawValue(`coordY${fromId}`, `coordY${toId}`); + } + + copyRawValue(fromElementId, toElementId) { + const fromElement = document.getElementById(fromElementId); + const toElement = document.getElementById(toElementId); + if (fromElement.dataset.rawValue === undefined) { + delete toElement.dataset.rawValue; + } else { + toElement.dataset.rawValue = fromElement.dataset.rawValue; + } + } + + removeTableRow(id) { + if (id <= this.num()) { + this.array[id - 1].remove(); + this.remove(id); + return; + } + + let inputTable = document.getElementById('inputTable'); + if (this.tableStarRowCount() > MIN_STAR_ROWS) { + inputTable.deleteRow(id + 1); + for (let i = id; i <= this.tableStarRowCount(); i++) { + this.renumberTableRow(i); + this.bindTableRow(i); + } + } else { + this.clearTableRowData(id); + this.bindTableRow(id); + } + this.interactPhoto.updateCeleStatus(); + } + + renumberTableRow(id) { + let inputTable = document.getElementById('inputTable'); + const row = inputTable.rows[id + 1]; + if (!row) return; + + row.cells[0].innerHTML = id; + row.querySelectorAll('[id]').forEach((element) => { + element.id = element.id.replace(/\d+$/, id); + }); + const removeButton = row.querySelector('.removeCeleRow'); + if (removeButton) removeButton.dataset.starId = id; } /** @@ -163,45 +302,7 @@ class CeleArray extends markerArray { // 对后面的星星进行 id 更新 for (let celeBody of this.array) { if (celeBody.id > id) { - document.getElementById(`name${celeBody.id - 1}`).value = document.getElementById( - `name${celeBody.id}` - ).value; - document.getElementById(`hAngleH${celeBody.id - 1}`).textContent = document.getElementById( - `hAngleH${celeBody.id}` - ).textContent; - document.getElementById(`hAngleM${celeBody.id - 1}`).textContent = document.getElementById( - `hAngleM${celeBody.id}` - ).textContent; - document.getElementById(`hAngleS${celeBody.id - 1}`).textContent = document.getElementById( - `hAngleS${celeBody.id}` - ).textContent; - document.getElementById(`declinD${celeBody.id - 1}`).textContent = document.getElementById( - `declinD${celeBody.id}` - ).textContent; - document.getElementById(`declinM${celeBody.id - 1}`).textContent = document.getElementById( - `declinM${celeBody.id}` - ).textContent; - document.getElementById(`declinS${celeBody.id - 1}`).textContent = document.getElementById( - `declinS${celeBody.id}` - ).textContent; - document.getElementById(`coordX${celeBody.id - 1}`).value = document.getElementById( - `coordX${celeBody.id}` - ).value; - document.getElementById(`coordY${celeBody.id - 1}`).value = document.getElementById( - `coordY${celeBody.id}` - ).value; - document.getElementById(`name${celeBody.id - 1}`).oninput = document.getElementById( - `name${celeBody.id}` - ).oninput; - document.getElementById(`name${celeBody.id - 1}`).onfocus = document.getElementById( - `name${celeBody.id}` - ).onfocus; - document.getElementById(`coordX${celeBody.id - 1}`).oninput = document.getElementById( - `coordX${celeBody.id}` - ).oninput; - document.getElementById(`coordY${celeBody.id - 1}`).oninput = document.getElementById( - `coordY${celeBody.id}` - ).oninput; + this.copyTableRowData(celeBody.id, celeBody.id - 1); celeBody.removeTableData(); celeBody.id--; celeBody.onRename(); @@ -211,37 +312,37 @@ class CeleArray extends markerArray { this.array.splice(id - 1, 1); // 删除最后一行表格 let inputTable = document.getElementById('inputTable'); - if (this.num() >= 5 && inputTable.rows.length - 2 > 5) { + if (inputTable.rows.length - 2 > MIN_STAR_ROWS) { inputTable.deleteRow(inputTable.rows.length - 1); } + for (let i = 1; i <= this.tableStarRowCount(); i++) { + this.bindTableRow(i); + } + this.interactPhoto.updateCeleStatus(); } clear() { + let inputTable = document.getElementById('inputTable'); + while (inputTable.rows.length - 2 > MIN_STAR_ROWS) { + inputTable.deleteRow(inputTable.rows.length - 1); + } // 清空表格数据 - for (let i = 1; i <= 5; i++) { - document.getElementById(`name${i}`).value = ''; - document.getElementById(`hAngleH${i}`).textContent = ''; - document.getElementById(`hAngleM${i}`).textContent = ''; - document.getElementById(`hAngleS${i}`).textContent = ''; - document.getElementById(`declinD${i}`).textContent = ''; - document.getElementById(`declinM${i}`).textContent = ''; - document.getElementById(`declinS${i}`).textContent = ''; - document.getElementById(`coordX${i}`).value = ''; - document.getElementById(`coordY${i}`).value = ''; + for (let i = 1; i <= this.tableStarRowCount(); i++) { + this.clearTableRowData(i); document.getElementById(`name${i}`).oninput = null; document.getElementById(`name${i}`).onfocus = null; document.getElementById(`coordX${i}`).oninput = null; document.getElementById(`coordY${i}`).oninput = null; } - let inputTable = document.getElementById('inputTable'); - while (inputTable.rows.length - 2 > 5) { - inputTable.deleteRow(inputTable.rows.length - 1); - } // 清空星星及其数组 for (let i of this.array) { i.remove(); } this.array = []; + for (let i = 1; i <= this.tableStarRowCount(); i++) { + this.bindTableRow(i); + } + this.interactPhoto.updateCeleStatus(); } } diff --git a/src/interface/functions/AutoComplete.js b/src/interface/functions/AutoComplete.js index 9380696..f3e76b3 100644 --- a/src/interface/functions/AutoComplete.js +++ b/src/interface/functions/AutoComplete.js @@ -55,14 +55,25 @@ function autoCompleteStarName(inp) { inp.addEventListener('keydown', function (e) { let divA = document.getElementById(this.id + '-autocomplete'); if (divA) var items = divA.getElementsByTagName('div'); - if (e.keyCode == 38 || (e.keyCode == 9 && e.shiftKey)) { - //up or shift+tab + if (e.keyCode == 9) { + // tab/shift+tab: move between celestial-name inputs, not autocomplete items + const currentId = this.id.match(/^name(\d+)$/); + const nextId = currentId ? Number(currentId[1]) + (e.shiftKey ? -1 : 1) : null; + const nextInput = nextId ? document.getElementById(`name${nextId}`) : null; + + closeAllLists(); + if (nextInput) { + e.preventDefault(); + nextInput.focus(); + } + } else if (e.keyCode == 38) { + //up e.preventDefault(); currentFocus--; addActive(items); fixScrolling(items); - } else if (e.keyCode == 40 || e.keyCode == 9) { - //down or tab + } else if (e.keyCode == 40) { + //down e.preventDefault(); currentFocus++; addActive(items); diff --git a/src/interface/functions/CeleRecognition.js b/src/interface/functions/CeleRecognition.js index 455303e..79fe9b9 100644 --- a/src/interface/functions/CeleRecognition.js +++ b/src/interface/functions/CeleRecognition.js @@ -2,18 +2,11 @@ import { DefaultbuttonFunctioner } from './Default.js'; import { post, setHADE } from '../utils.js'; import { BACKEND_API } from '../../config.js'; -const recognitionStatus = { - READY: 0, // 按钮未激活 - SUBMITTING: 1, // 准备提交数据并申请排队 - SOLVING: 2, // 等待Astrometry求解 - RECOGNIZING: 3, // 等待后端解析星名 -}; - // 天体识别按钮功能类 class RecognizeStars extends DefaultbuttonFunctioner { constructor(interactPhoto) { super(interactPhoto); - this.status = recognitionStatus.SUBMITTING; // 识别的状态 + this.isRecognizing = false; // 是否正在自动识星 this.xy = null; // 所有天体的图上坐标 } @@ -21,29 +14,28 @@ class RecognizeStars extends DefaultbuttonFunctioner { super.onClick(); if (!this.interactPhoto.movable) return; - if (this.status === recognitionStatus.READY) { - // 检查数据 - if (this.interactPhoto.CeleArray.num() < 3) { - this.interactPhoto.tips.innerHTML = '请至少选择三颗星'; - return; - } - - this.interactPhoto.buttonFunctioner = this; - this.status === recognitionStatus.SUBMITTING; - } else { + if (this.isRecognizing) { // 自动识星可能比较耗时,可以让用户取消 this.clearData(); this.interactPhoto.resetbuttonFunctioner(); this.interactPhoto.tips.innerHTML = '已取消自动识星'; + return; } - if (this.status === recognitionStatus.SUBMITTING) { - this.submitData(); + // 检查数据 + const count = this.interactPhoto.CeleArray.num(); + if (count < 3) { + this.interactPhoto.tips.innerHTML = `请至少选择三颗星,当前已标记 ${count} 个`; + return; } + + this.interactPhoto.buttonFunctioner = this; + this.isRecognizing = true; + this.submitData(); } clearData() { - this.status = recognitionStatus.SUBMITTING; + this.isRecognizing = false; this.xy = null; } diff --git a/src/interface/functions/PickCele.js b/src/interface/functions/PickCele.js index 6330f32..90b52fb 100644 --- a/src/interface/functions/PickCele.js +++ b/src/interface/functions/PickCele.js @@ -48,10 +48,6 @@ class PickCele extends DefaultbuttonFunctioner { // 添加星星点的函数 addStarAtPoint(x, y) { - // 保留两位小数 - x = Math.round(x * 100) / 100; - y = Math.round(y * 100) / 100; - this.interactPhoto.CeleArray.add(x, y); } } diff --git a/src/interface/init.js b/src/interface/init.js index 5b757f1..3f9109b 100644 --- a/src/interface/init.js +++ b/src/interface/init.js @@ -1,11 +1,11 @@ import { Canvas, IText } from 'fabric'; -import { autoCompleteStarName } from './functions/AutoComplete.js'; // 初始化页面元素 function initializeElements(interactPhoto) { interactPhoto.container = document.getElementById('box'); interactPhoto.cursorCrd = document.getElementById('cursorCrd'); interactPhoto.tips = document.getElementById('canvasStatus'); + interactPhoto.celeStatus = document.getElementById('celeStatus'); interactPhoto.inputTable = document.getElementById('inputTable'); interactPhoto.date = document.getElementById('setDate'); interactPhoto.time = document.getElementById('setTime'); @@ -108,11 +108,12 @@ function initializeEvents(eventManager) { document .getElementById('recognizeStars') .addEventListener('click', eventManager.recognizeStars.onClick.bind(eventManager.recognizeStars)); + document.getElementById('addCeleRow').addEventListener('click', () => { + interactPhoto.CeleArray.addEmptyRow(); + }); //为星体名称输入框启用自动补全 - for (let i = 1; i <= 5; i++) { - autoCompleteStarName(document.getElementById(`name${i}`)); - } + interactPhoto.CeleArray.initializeTableRows(); } // 初始化地图 diff --git a/src/interface/utils.js b/src/interface/utils.js index 4c0c82a..134045c 100644 --- a/src/interface/utils.js +++ b/src/interface/utils.js @@ -2,8 +2,10 @@ function getOriginalStars(interactPhoto) { let stars = []; for (let i = 1; i <= interactPhoto.CeleArray.num(); i++) { - let coordX = parseFloat(document.getElementById(`coordX${i}`).value); - let coordY = parseFloat(document.getElementById(`coordY${i}`).value); + const coordXInput = document.getElementById(`coordX${i}`); + const coordYInput = document.getElementById(`coordY${i}`); + let coordX = parseFloat(coordXInput.dataset.rawValue ?? coordXInput.value); + let coordY = parseFloat(coordYInput.dataset.rawValue ?? coordYInput.value); let name = document.getElementById(`name${i}`).value; stars.push({ x: coordX, @@ -32,13 +34,18 @@ function getGlobalPLPointsCoord(interactPhoto) { // 设置参考时角和赤纬,将角度数值化为度/时分秒形式 function setHADE(id, hourAngle, declination) { + const rawHourAngle = hourAngle; + const rawDeclination = declination; + let sign = hourAngle < 0 ? '-' : ''; hourAngle = Math.abs(hourAngle) / 15; document.getElementById(`hAngleH${id}`).textContent = sign + parseInt(hourAngle); hourAngle = (hourAngle - parseInt(hourAngle)) * 60; document.getElementById(`hAngleM${id}`).textContent = parseInt(hourAngle); hourAngle = (hourAngle - parseInt(hourAngle)) * 60; - document.getElementById(`hAngleS${id}`).textContent = hourAngle; + const hAngleS = document.getElementById(`hAngleS${id}`); + hAngleS.textContent = roundTo(hourAngle, 2); + hAngleS.dataset.rawValue = rawHourAngle; sign = declination < 0 ? '-' : ''; declination = Math.abs(declination); @@ -46,11 +53,26 @@ function setHADE(id, hourAngle, declination) { declination = (declination - parseInt(declination)) * 60; document.getElementById(`declinM${id}`).textContent = parseInt(declination); declination = (declination - parseInt(declination)) * 60; - document.getElementById(`declinS${id}`).textContent = declination; + const declinS = document.getElementById(`declinS${id}`); + declinS.textContent = roundTo(declination, 2); + declinS.dataset.rawValue = rawDeclination; } // 转换参考时角和赤纬,将度/时分秒形式转化为角度数值 function getHADE(id) { + const hAngleSInput = document.getElementById(`hAngleS${id}`); + const declinSInput = document.getElementById(`declinS${id}`); + const rawHourAngle = parseFloat(hAngleSInput.dataset.rawValue); + const rawDeclination = parseFloat(declinSInput.dataset.rawValue); + + if ( + Number.isFinite(rawHourAngle) && + Number.isFinite(rawDeclination) && + isDisplayedHADEUnchanged(id, rawHourAngle, rawDeclination) + ) { + return [rawHourAngle, rawDeclination]; + } + let hAngleH = parseInt(document.getElementById(`hAngleH${id}`).textContent); let hAngleM = parseInt(document.getElementById(`hAngleM${id}`).textContent); let hAngleS = parseFloat(document.getElementById(`hAngleS${id}`).textContent); @@ -64,6 +86,43 @@ function getHADE(id) { return [hourAngle, declination]; } +function roundTo(num, digits) { + const tmp = 10 ** digits; + return Math.round(num * tmp) / tmp; +} + +function formatHADE(hourAngle, declination) { + let sign = hourAngle < 0 ? '-' : ''; + hourAngle = Math.abs(hourAngle) / 15; + const hAngleH = sign + parseInt(hourAngle); + hourAngle = (hourAngle - parseInt(hourAngle)) * 60; + const hAngleM = String(parseInt(hourAngle)); + hourAngle = (hourAngle - parseInt(hourAngle)) * 60; + const hAngleS = String(roundTo(hourAngle, 2)); + + sign = declination < 0 ? '-' : ''; + declination = Math.abs(declination); + const declinD = sign + parseInt(declination); + declination = (declination - parseInt(declination)) * 60; + const declinM = String(parseInt(declination)); + declination = (declination - parseInt(declination)) * 60; + const declinS = String(roundTo(declination, 2)); + + return { hAngleH, hAngleM, hAngleS, declinD, declinM, declinS }; +} + +function isDisplayedHADEUnchanged(id, hourAngle, declination) { + const displayed = formatHADE(hourAngle, declination); + return ( + document.getElementById(`hAngleH${id}`).textContent === displayed.hAngleH && + document.getElementById(`hAngleM${id}`).textContent === displayed.hAngleM && + document.getElementById(`hAngleS${id}`).textContent === displayed.hAngleS && + document.getElementById(`declinD${id}`).textContent === displayed.declinD && + document.getElementById(`declinM${id}`).textContent === displayed.declinM && + document.getElementById(`declinS${id}`).textContent === displayed.declinS + ); +} + // json数据的POST请求 async function post(url, data, Type) { try {