docs: case04 Readme.html 新增交互式轨道示意图
使用 HTML5 Canvas + JavaScript 绘制椭圆轨道图, 支持滑块调整偏心率 e(0~0.85),实时更新: - 椭圆形状变化 - a/b/c 参数标注 - 近日点/远日点数值 - 速度矢量方向 - 底部信息面板
This commit is contained in:
+302
-4
@@ -116,8 +116,69 @@ MathJax = {
|
|||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.diagram-wrap {
|
||||||
|
background: #0d1117;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px;
|
||||||
|
margin: 16px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.diagram-wrap canvas {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.diagram-controls {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
.diagram-controls label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-dim);
|
||||||
|
}
|
||||||
|
.diagram-controls input[type="range"] {
|
||||||
|
width: 200px;
|
||||||
|
accent-color: var(--accent);
|
||||||
|
}
|
||||||
|
.diagram-controls .val {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--teal);
|
||||||
|
min-width: 48px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.diagram-info {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--text-dim);
|
||||||
|
}
|
||||||
|
.diagram-info span {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.diagram-info .dot {
|
||||||
|
display: inline-block;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
body { padding: 16px; }
|
body { padding: 16px; }
|
||||||
|
.diagram-controls { flex-direction: column; gap: 8px; }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -175,7 +236,20 @@ MathJax = {
|
|||||||
|
|
||||||
<h2>三、轨道力学</h2>
|
<h2>三、轨道力学</h2>
|
||||||
|
|
||||||
<h3>3.1 偏心率定义</h3>
|
<h3>3.1 交互式轨道示意图</h3>
|
||||||
|
|
||||||
|
<p>拖动下方滑块改变偏心率 $e$,观察轨道形状的变化和参数标注:</p>
|
||||||
|
|
||||||
|
<div class="diagram-wrap">
|
||||||
|
<canvas id="orbitCanvas" width="760" height="400"></canvas>
|
||||||
|
<div class="diagram-controls">
|
||||||
|
<label>偏心率 e = <span class="val" id="eDisplay">0.50</span></label>
|
||||||
|
<input type="range" id="eSlider" min="0" max="85" value="50">
|
||||||
|
</div>
|
||||||
|
<div class="diagram-info" id="diagramInfo"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>3.2 偏心率定义</h3>
|
||||||
|
|
||||||
<div class="highlight-eq">
|
<div class="highlight-eq">
|
||||||
<p>偏心率 $e$ 描述椭圆轨道偏离正圆的程度:</p>
|
<p>偏心率 $e$ 描述椭圆轨道偏离正圆的程度:</p>
|
||||||
@@ -193,7 +267,7 @@ MathJax = {
|
|||||||
<tr><td>$e > 1$</td><td>双曲线</td><td>飞越轨道,速度超过逃逸速度</td></tr>
|
<tr><td>$e > 1$</td><td>双曲线</td><td>飞越轨道,速度超过逃逸速度</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3>3.2 半长轴与半短轴的关系</h3>
|
<h3>3.3 半长轴与半短轴的关系</h3>
|
||||||
|
|
||||||
<div class="highlight-eq">
|
<div class="highlight-eq">
|
||||||
<div class="formula-block">
|
<div class="formula-block">
|
||||||
@@ -202,7 +276,7 @@ MathJax = {
|
|||||||
<p>当 $e \ll 1$ 时,$b \approx a\left(1 - \dfrac{e^2}{2}\right)$,椭圆度非常微小。</p>
|
<p>当 $e \ll 1$ 时,$b \approx a\left(1 - \dfrac{e^2}{2}\right)$,椭圆度非常微小。</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>3.3 近日点与远日点</h3>
|
<h3>3.4 近日点与远日点</h3>
|
||||||
|
|
||||||
<div class="highlight-eq">
|
<div class="highlight-eq">
|
||||||
<p>近日点(距太阳最近)和远日点(距太阳最远)的距离分别为:</p>
|
<p>近日点(距太阳最近)和远日点(距太阳最远)的距离分别为:</p>
|
||||||
@@ -216,7 +290,7 @@ MathJax = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>3.4 开普勒三大定律</h3>
|
<h3>3.5 开普勒三大定律</h3>
|
||||||
|
|
||||||
<ol>
|
<ol>
|
||||||
<li><strong>椭圆定律</strong>:行星轨道是椭圆,太阳位于椭圆的一个焦点上。</li>
|
<li><strong>椭圆定律</strong>:行星轨道是椭圆,太阳位于椭圆的一个焦点上。</li>
|
||||||
@@ -290,5 +364,229 @@ MathJax = {
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var canvas = document.getElementById('orbitCanvas');
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
var slider = document.getElementById('eSlider');
|
||||||
|
var eDisplay = document.getElementById('eDisplay');
|
||||||
|
var infoDiv = document.getElementById('diagramInfo');
|
||||||
|
|
||||||
|
var W = 760, H = 400;
|
||||||
|
var cx = 380, cy = 200;
|
||||||
|
|
||||||
|
// 实际绘图区域半径
|
||||||
|
var A = 140;
|
||||||
|
|
||||||
|
function draw(e) {
|
||||||
|
ctx.clearRect(0, 0, W, H);
|
||||||
|
|
||||||
|
var b = A * Math.sqrt(1 - e * e);
|
||||||
|
var f = e * A;
|
||||||
|
|
||||||
|
// 长轴辅助线
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - A - 20, cy);
|
||||||
|
ctx.lineTo(cx + A + 20, cy);
|
||||||
|
ctx.strokeStyle = '#30363d';
|
||||||
|
ctx.lineWidth = 0.5;
|
||||||
|
ctx.setLineDash([4, 3]);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.setLineDash([]);
|
||||||
|
|
||||||
|
// 椭圆轨道
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.ellipse(cx - f, cy, A, b, 0, 0, Math.PI * 2);
|
||||||
|
ctx.strokeStyle = '#58a6ff';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// 半长轴 a(标注线)
|
||||||
|
var aY = cy + 28;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - f, aY);
|
||||||
|
ctx.lineTo(cx - f + A, aY);
|
||||||
|
ctx.strokeStyle = '#c9d1d9';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
// 箭头
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - f + 6, aY - 4);
|
||||||
|
ctx.lineTo(cx - f, aY);
|
||||||
|
ctx.lineTo(cx - f + 6, aY + 4);
|
||||||
|
ctx.strokeStyle = '#c9d1d9';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - f + A - 6, aY - 4);
|
||||||
|
ctx.lineTo(cx - f + A, aY);
|
||||||
|
ctx.lineTo(cx - f + A - 6, aY + 4);
|
||||||
|
ctx.strokeStyle = '#c9d1d9';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = '#c9d1d9';
|
||||||
|
ctx.font = '13px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'top';
|
||||||
|
ctx.fillText('a = ' + A.toFixed(0), cx - f + A/2, aY + 6);
|
||||||
|
|
||||||
|
// 偏心距 c = ea 标注
|
||||||
|
var cY = cy - b - 20;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - f, cY);
|
||||||
|
ctx.lineTo(cx, cY);
|
||||||
|
ctx.strokeStyle = '#d29922';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - f + 5, cY - 4);
|
||||||
|
ctx.lineTo(cx - f, cY);
|
||||||
|
ctx.lineTo(cx - f + 5, cY + 4);
|
||||||
|
ctx.strokeStyle = '#d29922';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(cx - 5, cY - 4);
|
||||||
|
ctx.lineTo(cx, cY);
|
||||||
|
ctx.lineTo(cx - 5, cY + 4);
|
||||||
|
ctx.strokeStyle = '#d29922';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = '#d29922';
|
||||||
|
ctx.font = '13px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'bottom';
|
||||||
|
ctx.fillText('c = ea = ' + f.toFixed(1), cx - f/2, cY - 4);
|
||||||
|
|
||||||
|
// 半短轴 b 标注
|
||||||
|
var bX = cx - f + A + 18;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(bX, cy);
|
||||||
|
ctx.lineTo(bX, cy - b);
|
||||||
|
ctx.strokeStyle = '#3fb950';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(bX - 4, cy - 6);
|
||||||
|
ctx.lineTo(bX, cy);
|
||||||
|
ctx.lineTo(bX + 4, cy - 6);
|
||||||
|
ctx.strokeStyle = '#3fb950';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(bX - 4, cy - b + 6);
|
||||||
|
ctx.lineTo(bX, cy - b);
|
||||||
|
ctx.lineTo(bX + 4, cy - b + 6);
|
||||||
|
ctx.strokeStyle = '#3fb950';
|
||||||
|
ctx.lineWidth = 1.5;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = '#3fb950';
|
||||||
|
ctx.font = '13px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'left';
|
||||||
|
ctx.textBaseline = 'middle';
|
||||||
|
ctx.fillText('b = ' + b.toFixed(1), bX + 8, cy - b/2);
|
||||||
|
|
||||||
|
// 太阳(焦点)
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(cx, cy, 7, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = '#d29922';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#f0883e';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = '#f0f6fc';
|
||||||
|
ctx.font = '13px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'bottom';
|
||||||
|
ctx.fillText('太阳(焦点)', cx, cy - 12);
|
||||||
|
|
||||||
|
// 近日点标注
|
||||||
|
var periX = cx - f - A;
|
||||||
|
ctx.fillStyle = '#58a6ff';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(periX, cy, 4, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.fillStyle = '#8b949e';
|
||||||
|
ctx.font = '12px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'top';
|
||||||
|
ctx.fillText('近日点 r = a(1-e) = ' + (A * (1 - e)).toFixed(1), periX, cy + 12);
|
||||||
|
|
||||||
|
// 远日点标注
|
||||||
|
var apX = cx - f + A;
|
||||||
|
ctx.fillStyle = '#58a6ff';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(apX, cy, 4, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.fillStyle = '#8b949e';
|
||||||
|
ctx.font = '12px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'center';
|
||||||
|
ctx.textBaseline = 'top';
|
||||||
|
ctx.fillText('远日点 r = a(1+e) = ' + (A * (1 + e)).toFixed(1), apX, cy + 12);
|
||||||
|
|
||||||
|
// 地球(轨道上的点)
|
||||||
|
var angle = 0.4;
|
||||||
|
var ex = cx - f + A * Math.cos(angle);
|
||||||
|
var ey = cy - b * Math.sin(angle);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(ex, ey, 5, 0, Math.PI * 2);
|
||||||
|
ctx.fillStyle = '#58a6ff';
|
||||||
|
ctx.fill();
|
||||||
|
ctx.strokeStyle = '#1f6feb';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = '#58a6ff';
|
||||||
|
ctx.font = '12px "Segoe UI", Arial, sans-serif';
|
||||||
|
ctx.textAlign = 'left';
|
||||||
|
ctx.textBaseline = 'bottom';
|
||||||
|
ctx.fillText('地球', ex + 8, ey);
|
||||||
|
|
||||||
|
// 速度矢量
|
||||||
|
var vlen = 32;
|
||||||
|
var vx = -A * Math.sin(angle) * 0.7;
|
||||||
|
var vy = b * Math.cos(angle) * 0.7;
|
||||||
|
var vl = Math.sqrt(vx*vx + vy*vy);
|
||||||
|
if (vl > 0) {
|
||||||
|
vx = vx / vl * vlen;
|
||||||
|
vy = vy / vl * vlen;
|
||||||
|
}
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(ex, ey);
|
||||||
|
ctx.lineTo(ex + vx, ey + vy);
|
||||||
|
ctx.strokeStyle = '#3fb950';
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.beginPath();
|
||||||
|
var tipX = ex + vx, tipY = ey + vy;
|
||||||
|
var a1 = 0.3;
|
||||||
|
ctx.moveTo(tipX, tipY);
|
||||||
|
ctx.lineTo(tipX - vx * a1 + vy * a1 * 0.5, tipY - vy * a1 - vx * a1 * 0.5);
|
||||||
|
ctx.lineTo(tipX - vx * a1 - vy * a1 * 0.5, tipY - vy * a1 + vx * a1 * 0.5);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fillStyle = '#3fb950';
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// 信息面板
|
||||||
|
var roundE = Math.round(e * 10000) / 10000;
|
||||||
|
infoDiv.innerHTML =
|
||||||
|
'<span><span class="dot" style="background:#58a6ff"></span>椭圆轨道 e = ' + roundE.toFixed(4) + '</span>' +
|
||||||
|
'<span><span class="dot" style="background:#d29922"></span>偏心距 c = ' + f.toFixed(1) + '</span>' +
|
||||||
|
'<span><span class="dot" style="background:#3fb950"></span>b/a = ' + (b / A).toFixed(4) + '</span>' +
|
||||||
|
'<span>近日点 ' + (A * (1 - e)).toFixed(1) + ' / 远日点 ' + (A * (1 + e)).toFixed(1) + '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var val = parseInt(slider.value);
|
||||||
|
var e = val / 100;
|
||||||
|
eDisplay.textContent = e.toFixed(2);
|
||||||
|
draw(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
slider.addEventListener('input', update);
|
||||||
|
update();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user