坐标

March 26, 2025

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>坐标计算器</title> <style> :root { --primary-color: #4361ee; --primary-dark: #3a56d4; --secondary-color: #3f8efc; --accent-color: #2ec4b6; --light-bg: #f8f9fa; --card-bg: #ffffff; --text-color: #333; --text-secondary: #666; --border-radius: 10px; --box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); --transition: all 0.3s ease; } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; background-color: var(--light-bg); color: var(--text-color); padding: 20px; } .container { max-width: 900px; margin: 0 auto; background: var(--card-bg); padding: 30px; border-radius: var(--border-radius); box-shadow: var(--box-shadow); } h1 { text-align: center; color: var(--primary-color); margin-bottom: 25px; font-size: 2.2rem; } .card { background: var(--card-bg); border-radius: var(--border-radius); padding: 25px; margin-bottom: 25px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); transition: var(--transition); } .card:hover { box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); } .card-header { display: flex; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #eee; } .card-icon { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; background-color: var(--primary-color); color: white; border-radius: 50%; margin-right: 10px; } .card-title { font-size: 1.3rem; font-weight: 600; color: var(--primary-color); } .description { background-color: #f0f7ff; padding: 15px; border-radius: var(--border-radius); margin-bottom: 25px; border-left: 4px solid var(--secondary-color); color: var(--text-secondary); } .form-group { margin-bottom: 20px; } label { display: block; margin-bottom: 8px; font-weight: 500; color: var(--text-secondary); } input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; transition: var(--transition); } input:focus { outline: none; border-color: var(--secondary-color); box-shadow: 0 0 0 3px rgba(63, 142, 252, 0.2); } .row { display: flex; gap: 20px; margin-bottom: 10px; } .col { flex: 1; } button { width: 100%; padding: 14px; background-color: var(--primary-color); color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 18px; font-weight: 600; letter-spacing: 0.5px; transition: var(--transition); margin-top: 15px; box-shadow: 0 4px 10px rgba(67, 97, 238, 0.3); } button:hover { background-color: var(--primary-dark); transform: translateY(-2px); box-shadow: 0 6px 15px rgba(67, 97, 238, 0.4); } button:active { transform: translateY(0); box-shadow: 0 2px 5px rgba(67, 97, 238, 0.4); } .error { color: #e63946; background-color: #ffe5e5; padding: 15px; border-radius: 6px; margin: 20px 0; border-left: 4px solid #e63946; display: none; } .results-container { display: flex; flex-direction: column; gap: 25px; } .current-value { padding: 15px; background-color: #e7f3ff; border-radius: var(--border-radius); text-align: center; font-weight: 600; color: var(--primary-color); margin: 10px 0 20px 0; border: 1px solid #c1ddff; font-size: 1.1rem; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); } table { width: 100%; border-collapse: collapse; margin-top: 10px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); border-radius: 8px; overflow: hidden; } th, td { padding: 12px; text-align: center; } th { background-color: var(--primary-color); color: white; font-weight: 500; } tr:nth-child(even) { background-color: #f0f7ff; } tr:hover { background-color: #e2eeff; } .result-section { background-color: var(--card-bg); border-radius: var(--border-radius); padding: 20px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); } .result-header { display: flex; align-items: center; margin-bottom: 15px; } .result-icon { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; background-color: var(--accent-color); color: white; border-radius: 50%; margin-right: 10px; } .result-title { font-size: 1.1rem; font-weight: 600; color: var(--accent-color); } @media (max-width: 768px) { .row { flex-direction: column; gap: 10px; } .container { padding: 20px; } } </style> </head> <body> <div class="container"> <h1>坐标计算器</h1> <div class="description"> <p>本计算器基于公式 x=initial_x + step_x*n 和 y=initial_y + step_y*n,生成与当前坐标相近的系列坐标点。</p> </div> <div class="card"> <div class="card-header"> <div class="card-icon">⚙️</div> <div class="card-title">初始设置</div> </div> <div class="row"> <div class="col"> <div class="form-group"> <label for="initialX">初始X坐标:</label> <input type="number" id="initialX" value="0" min="0" step="any" placeholder="设置起始X值"> </div> </div> <div class="col"> <div class="form-group"> <label for="stepX">X步长:</label> <input type="number" id="stepX" value="1" min="0" step="any" placeholder="设置X增量"> </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> <label for="initialY">初始Y坐标:</label> <input type="number" id="initialY" value="0" min="0" step="any" placeholder="设置起始Y值"> </div> </div> <div class="col"> <div class="form-group"> <label for="stepY">Y步长:</label> <input type="number" id="stepY" value="1" min="0" step="any" placeholder="设置Y增量"> </div> </div> </div> </div> <div class="card"> <div class="card-header"> <div class="card-icon">📍</div> <div class="card-title">当前坐标</div> </div> <div class="row"> <div class="col"> <div class="form-group"> <label for="inputX">当前X坐标:</label> <input type="number" id="inputX" min="0" step="any" placeholder="输入当前X坐标"> </div> </div> <div class="col"> <div class="form-group"> <label for="inputY">当前Y坐标:</label> <input type="number" id="inputY" min="0" step="any" placeholder="输入当前Y坐标"> </div> </div> </div> <button onclick="calculate()">生成坐标系列</button> </div> <div id="errorMessage" class="error"></div> <div id="results" class="results-container" style="display: none;"> <div id="currentValueContainer" class="current-value"></div> <div class="result-section"> <div class="result-header"> <div class="result-icon"></div> <div class="result-title">小于当前坐标的系列</div> </div> <table id="smallerTable"> <thead> <tr> <th>X 坐标</th> <th>Y 坐标</th> </tr> </thead> <tbody id="smallerBody"></tbody> </table> </div> <div class="result-section"> <div class="result-header"> <div class="result-icon"></div> <div class="result-title">大于当前坐标的系列</div> </div> <table id="largerTable"> <thead> <tr> <th>X 坐标</th> <th>Y 坐标</th> </tr> </thead> <tbody id="largerBody"></tbody> </table> </div> </div> </div> <script> function showError(message) { const errorElement = document.getElementById('errorMessage'); errorElement.textContent = message; errorElement.style.display = 'block'; document.getElementById('results').style.display = 'none'; } function hideError() { document.getElementById('errorMessage').style.display = 'none'; } function validatePositive(value, name) { if (value < 0) { return `${name} 必须为正数或零`; } return null; } function calculate() { hideError(); // 获取初始值和步长 const initialX = parseFloat(document.getElementById('initialX').value); const stepX = parseFloat(document.getElementById('stepX').value); const initialY = parseFloat(document.getElementById('initialY').value); const stepY = parseFloat(document.getElementById('stepY').value); // 获取当前值 const inputX = parseFloat(document.getElementById('inputX').value); const inputY = parseFloat(document.getElementById('inputY').value); // 验证所有值是否为数字 if (isNaN(initialX) || isNaN(stepX) || isNaN(initialY) || isNaN(stepY) || isNaN(inputX) || isNaN(inputY)) { showError('请输入有效的数值'); return; } // 验证所有值为正数或零 let errorMsg = validatePositive(initialX, '初始X坐标') || validatePositive(stepX, 'X步长') || validatePositive(initialY, '初始Y坐标') || validatePositive(stepY, 'Y步长') || validatePositive(inputX, '当前X坐标') || validatePositive(inputY, '当前Y坐标'); if (errorMsg) { showError(errorMsg); return; } // 验证步长不为零 if (stepX === 0 || stepY === 0) { showError('步长不能为0'); return; } // 计算X和Y对应的n值 const nX = Math.round((inputX - initialX) / stepX); const nY = Math.round((inputY - initialY) / stepY); // 使用平均n值作为最佳匹配 const n = Math.round((nX + nY) / 2); // 计算基于n的精确X和Y值 const exactX = initialX + stepX * n; const exactY = initialY + stepY * n; // 准备小于和大于的结果数组 const smallerResults = []; const largerResults = []; // 计算小于当前n的结果 for (let i = n - 1; smallerResults.length < 10 && i >= 0; i--) { const x = initialX + stepX * i; const y = initialY + stepY * i; // 过滤掉负数结果 if (x < 0 || y < 0) continue; // 插入到开头,确保值从小到大排序 smallerResults.unshift({ x: x, y: y }); } // 计算大于当前n的结果 for (let i = n + 1; largerResults.length < 10; i++) { const x = initialX + stepX * i; const y = initialY + stepY * i; // 过滤掉负数结果 if (x < 0 || y < 0) continue; largerResults.push({ x: x, y: y }); } // 显示当前最接近的值 const currentValueContainer = document.getElementById('currentValueContainer'); currentValueContainer.innerHTML = ` <div>输入坐标: (X=${inputX}, Y=${inputY})</div> <div>最接近的系列坐标: (X=${exactX.toFixed(6)}, Y=${exactY.toFixed(6)})</div> `; // 显示小于的结果 const smallerBody = document.getElementById('smallerBody'); smallerBody.innerHTML = ''; if (smallerResults.length === 0) { const row = document.createElement('tr'); const cell = document.createElement('td'); cell.colSpan = 2; cell.textContent = '没有小于该值的正数结果'; row.appendChild(cell); smallerBody.appendChild(row); } else { smallerResults.forEach(result => { const row = document.createElement('tr'); const xCell = document.createElement('td'); xCell.textContent = result.x.toFixed(6); const yCell = document.createElement('td'); yCell.textContent = result.y.toFixed(6); row.appendChild(xCell); row.appendChild(yCell); smallerBody.appendChild(row); }); } // 显示大于的结果 const largerBody = document.getElementById('largerBody'); largerBody.innerHTML = ''; if (largerResults.length === 0) { const row = document.createElement('tr'); const cell = document.createElement('td'); cell.colSpan = 2; cell.textContent = '没有大于该值的结果'; row.appendChild(cell); largerBody.appendChild(row); } else { largerResults.forEach(result => { const row = document.createElement('tr'); const xCell = document.createElement('td'); xCell.textContent = result.x.toFixed(6); const yCell = document.createElement('td'); yCell.textContent = result.y.toFixed(6); row.appendChild(xCell); row.appendChild(yCell); largerBody.appendChild(row); }); } // 显示结果区域,添加平滑过渡 const results = document.getElementById('results'); results.style.display = 'flex'; } </script> </body> </html>