docs: case04 Readme.html 新增月球绕地轨道交互图

- 月球轨道图使用绿色配色,与地球轨道图(蓝色)区分
- 默认偏心率 e=0.0549(月球真实值)
- 标注半长轴 a / 半短轴 b / 偏心距 c
- 标注近地点/远地点距离
- 地球在左焦点,月球在椭圆轨道运行
- 独立滑块控制月球偏心率
This commit is contained in:
2026-06-18 23:06:55 +08:00
parent 7078cbc744
commit c8d12e7f45
+233 -5
View File
@@ -250,7 +250,20 @@ MathJax = {
<div class="diagram-info" id="diagramInfo"></div>
</div>
<h3>3.2 偏心率定义</h3>
<h3>3.2 月球绕地球轨道</h3>
<p>拖动下方滑块改变月球轨道偏心率 $e_\text{moon}$(真实值 0.0549):</p>
<div class="diagram-wrap">
<canvas id="moonCanvas" width="760" height="400"></canvas>
<div class="diagram-controls">
<label>偏心率 e = <span class="val" id="moonEDisplay">0.0549</span>(月球真实值 0.0549</label>
<input type="range" id="moonESlider" min="0" max="850" value="55">
</div>
<div class="diagram-info" id="moonInfo"></div>
</div>
<h3>3.3 偏心率定义</h3>
<div class="highlight-eq">
<p>偏心率 $e$ 描述椭圆轨道偏离正圆的程度:</p>
@@ -263,12 +276,12 @@ MathJax = {
<table>
<tr><th>$e$ 值</th><th>轨道形状</th><th>说明</th></tr>
<tr><td>$e = 0$</td><td>正圆形</td><td>速度恒定,距离恒定</td></tr>
<tr><td>$0 &lt; e &lt; 1$</td><td>椭圆</td><td>近日点速度最大,远日点速度最小</td></tr>
<tr><td>$0 &lt; e &lt; 1$</td><td>椭圆</td><td>近日点/近地点速度最大,远日点/远地点速度最小</td></tr>
<tr><td>$e = 1$</td><td>抛物线</td><td>逃逸轨道,速度恰好达到逃逸速度</td></tr>
<tr><td>$e &gt; 1$</td><td>双曲线</td><td>飞越轨道,速度超过逃逸速度</td></tr>
</table>
<h3>3.3 半长轴与半短轴的关系</h3>
<h3>3.4 半长轴与半短轴的关系</h3>
<div class="highlight-eq">
<div class="formula-block">
@@ -277,7 +290,7 @@ MathJax = {
<p>当 $e \ll 1$ 时,$b \approx a\left(1 - \dfrac{e^2}{2}\right)$,椭圆度非常微小。</p>
</div>
<h3>3.4 近日点与远日点</h3>
<h3>3.5 近日点与远日点</h3>
<div class="highlight-eq">
<p>近日点(距太阳最近)和远日点(距太阳最远)的距离分别为:</p>
@@ -291,7 +304,7 @@ MathJax = {
</div>
</div>
<h3>3.5 开普勒三大定律</h3>
<h3>3.6 开普勒三大定律</h3>
<ol>
<li><strong>椭圆定律</strong>:行星轨道是椭圆,太阳位于椭圆的一个焦点上。</li>
@@ -587,6 +600,221 @@ MathJax = {
slider.addEventListener('input', update);
update();
})();
// ── 月球绕地球轨道图 ──
(function() {
var canvas = document.getElementById('moonCanvas');
var ctx = canvas.getContext('2d');
var slider = document.getElementById('moonESlider');
var eDisplay = document.getElementById('moonEDisplay');
var infoDiv = document.getElementById('moonInfo');
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([]);
// 椭圆轨道(中心在 cx+f,左焦点=cx 为地球)
ctx.beginPath();
ctx.ellipse(cx + f, cy, A, b, 0, 0, Math.PI * 2);
ctx.strokeStyle = '#7ee787';
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, cY);
ctx.lineTo(cx + f, cY);
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.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.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, 8, 0, Math.PI * 2);
ctx.fillStyle = '#58a6ff';
ctx.fill();
ctx.strokeStyle = '#1f6feb';
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 - 14);
// 近地点(左顶点:距地球最近)
var periX = cx + f - A;
ctx.fillStyle = '#7ee787';
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 = '#7ee787';
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.6;
var mx = cx + f + A * Math.cos(angle);
var my = cy - b * Math.sin(angle);
ctx.beginPath();
ctx.arc(mx, my, 4, 0, Math.PI * 2);
ctx.fillStyle = '#e2e8f0';
ctx.fill();
ctx.strokeStyle = '#8b949e';
ctx.lineWidth = 0.5;
ctx.stroke();
ctx.fillStyle = '#e2e8f0';
ctx.font = '12px "Segoe UI", Arial, sans-serif';
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
ctx.fillText('月球', mx + 8, my);
// 速度矢量
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(mx, my);
ctx.lineTo(mx + vx, my + vy);
ctx.strokeStyle = '#3fb950';
ctx.lineWidth = 2;
ctx.stroke();
var tipX = mx + vx, tipY = my + vy;
ctx.beginPath();
ctx.moveTo(tipX, tipY);
ctx.lineTo(tipX - vx*0.3 + vy*0.15, tipY - vy*0.3 - vx*0.15);
ctx.lineTo(tipX - vx*0.3 - vy*0.15, tipY - vy*0.3 + vx*0.15);
ctx.closePath();
ctx.fillStyle = '#3fb950';
ctx.fill();
// 信息面板
var roundE = Math.round(e * 10000) / 10000;
infoDiv.innerHTML =
'<span><span class="dot" style="background:#7ee787"></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 / 1000;
eDisplay.textContent = e.toFixed(4);
draw(e);
}
slider.addEventListener('input', update);
update();
})();
</script>
</body>