diff --git a/examples/case04/Readme.html b/examples/case04/Readme.html index 69c5fd9..4c2e8cf 100644 --- a/examples/case04/Readme.html +++ b/examples/case04/Readme.html @@ -250,7 +250,20 @@ MathJax = {
-

3.2 偏心率定义

+

3.2 月球绕地球轨道

+ +

拖动下方滑块改变月球轨道偏心率 $e_\text{moon}$(真实值 0.0549):

+ +
+ +
+ + +
+
+
+ +

3.3 偏心率定义

偏心率 $e$ 描述椭圆轨道偏离正圆的程度:

@@ -263,12 +276,12 @@ MathJax = { - +
$e$ 值轨道形状说明
$e = 0$正圆形速度恒定,距离恒定
$0 < e < 1$椭圆近日点速度最大,远日点速度最小
$0 < e < 1$椭圆近日点/近地点速度最大,远日点/远地点速度最小
$e = 1$抛物线逃逸轨道,速度恰好达到逃逸速度
$e > 1$双曲线飞越轨道,速度超过逃逸速度
-

3.3 半长轴与半短轴的关系

+

3.4 半长轴与半短轴的关系

@@ -277,7 +290,7 @@ MathJax = {

当 $e \ll 1$ 时,$b \approx a\left(1 - \dfrac{e^2}{2}\right)$,椭圆度非常微小。

-

3.4 近日点与远日点

+

3.5 近日点与远日点

近日点(距太阳最近)和远日点(距太阳最远)的距离分别为:

@@ -291,7 +304,7 @@ MathJax = {
-

3.5 开普勒三大定律

+

3.6 开普勒三大定律

  1. 椭圆定律:行星轨道是椭圆,太阳位于椭圆的一个焦点上。
  2. @@ -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 = + '椭圆轨道 e = ' + roundE.toFixed(4) + '' + + '偏心距 c = ' + f.toFixed(1) + '' + + 'b/a = ' + (b / A).toFixed(4) + '' + + '近地点 ' + (A * (1 - e)).toFixed(1) + ' / 远地点 ' + (A * (1 + e)).toFixed(1) + ''; + } + + function update() { + var val = parseInt(slider.value); + var e = val / 1000; + eDisplay.textContent = e.toFixed(4); + draw(e); + } + + slider.addEventListener('input', update); + update(); +})();