docs: case04 Readme.html 新增月球绕地轨道交互图
- 月球轨道图使用绿色配色,与地球轨道图(蓝色)区分 - 默认偏心率 e=0.0549(月球真实值) - 标注半长轴 a / 半短轴 b / 偏心距 c - 标注近地点/远地点距离 - 地球在左焦点,月球在椭圆轨道运行 - 独立滑块控制月球偏心率
This commit is contained in:
+233
-5
@@ -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 < e < 1$</td><td>椭圆</td><td>近日点速度最大,远日点速度最小</td></tr>
|
||||
<tr><td>$0 < e < 1$</td><td>椭圆</td><td>近日点/近地点速度最大,远日点/远地点速度最小</td></tr>
|
||||
<tr><td>$e = 1$</td><td>抛物线</td><td>逃逸轨道,速度恰好达到逃逸速度</td></tr>
|
||||
<tr><td>$e > 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>
|
||||
|
||||
Reference in New Issue
Block a user