分享图
动画工坊
引擎就绪
<!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 {
      --bg-space: #050811;
      --panel-bg: rgba(13, 22, 38, 0.72);
      --panel-border: rgba(56, 189, 248, 0.22);
      --accent-cyan: #38bdf8;
      --accent-gold: #f59e0b;
      --accent-emerald: #10b981;
      --accent-rose: #f43f5e;
      --text-muted: #64748b;
      --text-bright: #e2e8f0;
      --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
      --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
    }

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      user-select: none;
    }

    body {
      background-color: var(--bg-space);
      color: var(--text-bright);
      font-family: var(--font-sans);
      width: 100vw;
      height: 100vh;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
    }

    /* 主视区外层容器 */
    .viewport-wrapper {
      position: relative;
      width: 100%;
      height: 100%;
      max-width: 1600px;
      max-height: 900px;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
      background: radial-gradient(circle at 50% 40%, #0d1a30 0%, #050811 85%);
      box-shadow: 0 0 80px rgba(0, 0, 0, 0.8) inset;
    }

    svg#stage {
      width: 100%;
      height: 100%;
      display: block;
    }

    /* 微型遥测角标 - 严格边缘排布,不阻挡中心主视觉 */
    .hud-corner {
      position: absolute;
      z-index: 10;
      pointer-events: none;
      font-size: 11px;
      line-height: 1.4;
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      background: var(--panel-bg);
      border: 1px solid var(--panel-border);
      border-radius: 6px;
      padding: 8px 12px;
      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    }

    .hud-top-left {
      top: 18px;
      left: 20px;
      display: flex;
      flex-direction: column;
      gap: 3px;
    }

    .hud-top-left .title-tag {
      font-size: 13px;
      font-weight: 600;
      letter-spacing: 0.8px;
      color: var(--accent-cyan);
      display: flex;
      align-items: center;
      gap: 6px;
    }

    .pulse-dot {
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent-emerald);
      box-shadow: 0 0 8px var(--accent-emerald);
      animation: pulse 1.6s infinite ease-in-out;
    }

    @keyframes pulse {
      0%, 100% { opacity: 1; transform: scale(1); }
      50% { opacity: 0.3; transform: scale(0.8); }
    }

    .hud-top-right {
      top: 18px;
      right: 20px;
      display: flex;
      align-items: center;
      gap: 14px;
      font-family: var(--font-mono);
    }

    .time-badge {
      font-size: 16px;
      font-weight: 700;
      color: var(--accent-gold);
      text-shadow: 0 0 10px rgba(245, 158, 11, 0.4);
    }

    .phase-badge {
      display: inline-block;
      padding: 2px 7px;
      border-radius: 4px;
      background: rgba(56, 189, 248, 0.12);
      border: 1px solid var(--accent-cyan);
      color: var(--accent-cyan);
      font-size: 11px;
    }

    /* 底部极简紧凑遥测栏与交互区 */
    .hud-bottom-bar {
      position: absolute;
      bottom: 14px;
      left: 20px;
      right: 20px;
      z-index: 10;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      background: var(--panel-bg);
      border: 1px solid var(--panel-border);
      border-radius: 8px;
      padding: 8px 16px;
      pointer-events: auto;
    }

    .telemetry-group {
      display: flex;
      gap: 20px;
      align-items: center;
      flex-wrap: wrap;
    }

    .telemetry-item {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    .telemetry-label {
      font-size: 10px;
      color: var(--text-muted);
      letter-spacing: 0.5px;
    }

    .telemetry-val {
      font-family: var(--font-mono);
      font-size: 12px;
      font-weight: 600;
      color: var(--text-bright);
    }

    .control-group {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .btn-ctrl {
      background: rgba(56, 189, 248, 0.1);
      border: 1px solid rgba(56, 189, 248, 0.35);
      color: var(--text-bright);
      padding: 5px 11px;
      border-radius: 5px;
      font-size: 11px;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 5px;
      transition: all 0.2s ease;
    }

    .btn-ctrl:hover {
      background: rgba(56, 189, 248, 0.25);
      border-color: var(--accent-cyan);
      color: #fff;
    }

    .slider-container {
      display: flex;
      align-items: center;
      gap: 8px;
      font-size: 11px;
      color: var(--text-muted);
    }

    input[type="range"] {
      -webkit-appearance: none;
      width: 140px;
      height: 4px;
      border-radius: 2px;
      background: rgba(255, 255, 255, 0.15);
      outline: none;
      cursor: pointer;
    }

    input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: var(--accent-cyan);
      box-shadow: 0 0 6px var(--accent-cyan);
      cursor: pointer;
    }

    /* 动画与SVG样式 */
    .path-trajectory {
      stroke: rgba(56, 189, 248, 0.3);
      stroke-dasharray: 4, 4;
      fill: none;
    }

    .path-trajectory-glow {
      stroke: rgba(56, 189, 248, 0.15);
      stroke-width: 6;
      fill: none;
    }

    .grid-line {
      stroke: rgba(255, 255, 255, 0.05);
      stroke-dasharray: 2, 4;
    }

    .grid-text {
      fill: rgba(148, 163, 184, 0.5);
      font-size: 10px;
      font-family: var(--font-mono);
    }
  </style>
</head>
<body>

  <div class="viewport-wrapper">
    <!-- SVG 核心动画画布:居中展示长航时势能-电能协同闭环 -->
    <svg id="stage" viewBox="0 0 1200 680" preserveAspectRatio="xMidYMid meet">
      <defs>
        <!-- 天空昼夜环境光渐变 -->
        <linearGradient id="skyGrad" x1="0" y1="0" x2="0" y2="1">
          <stop id="skyStop1" offset="0%" stop-color="#040714" />
          <stop id="skyStop2" offset="100%" stop-color="#071224" />
        </linearGradient>

        <!-- 势能高度热力带渐变 -->
        <linearGradient id="altitudeGradient" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="rgba(16, 185, 129, 0.25)" />
          <stop offset="50%" stop-color="rgba(56, 189, 248, 0.1)" />
          <stop offset="100%" stop-color="rgba(2, 6, 23, 0)" />
        </linearGradient>

        <!-- 太阳耀斑光芒滤镜 -->
        <filter id="solarGlow" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur1" />
          <feGaussianBlur in="SourceGraphic" stdDeviation="20" result="blur2" />
          <feMerge>
            <feMergeNode in="blur2" />
            <feMergeNode in="blur1" />
            <feMergeNode in="SourceGraphic" />
          </feMerge>
        </filter>

        <!-- 机身能量流动辉光 -->
        <filter id="energyGlow" x="-30%" y="-30%" width="160%" height="160%">
          <feGaussianBlur stdDeviation="3.5" result="blur" />
          <feMerge>
            <feMergeNode in="blur" />
            <feMergeNode in="SourceGraphic" />
          </feMerge>
        </filter>

        <!-- GaAs 薄膜太阳能翼板图案 -->
        <pattern id="gaasPattern" width="10" height="8" patternUnits="userSpaceOnUse">
          <rect width="9" height="7" fill="rgba(30, 58, 138, 0.85)" stroke="rgba(56, 189, 248, 0.4)" stroke-width="0.5"/>
          <line x1="0" y1="4" x2="9" y2="4" stroke="rgba(96, 165, 250, 0.3)" stroke-width="0.5"/>
        </pattern>
      </defs>

      <!-- 动态天空背景 -->
      <rect x="0" y="0" width="1200" height="680" fill="url(#skyGrad)" id="skyRect" />

      <!-- 背景星空群 (夜间淡入) -->
      <g id="starField" opacity="0.6">
        <!-- 随机稀疏星点,增强深空沉浸感 -->
        <circle cx="120" cy="80" r="1" fill="#fff" opacity="0.8"/>
        <circle cx="280" cy="110" r="1.2" fill="#93c5fd" opacity="0.7"/>
        <circle cx="430" cy="65" r="0.8" fill="#fff" opacity="0.5"/>
        <circle cx="620" cy="95" r="1.5" fill="#fde047" opacity="0.6"/>
        <circle cx="790" cy="50" r="1" fill="#fff" opacity="0.8"/>
        <circle cx="980" cy="120" r="0.9" fill="#93c5fd" opacity="0.5"/>
        <circle cx="1110" cy="75" r="1.4" fill="#fff" opacity="0.9"/>
        <circle cx="210" cy="220" r="0.8" fill="#fff" opacity="0.4"/>
        <circle cx="850" cy="190" r="1" fill="#fff" opacity="0.6"/>
        <circle cx="1040" cy="260" r="0.7" fill="#67e8f9" opacity="0.5"/>
      </g>

      <!-- 高度参考标尺与水平等高虚线 -->
      <g id="altitudeGrid">
        <!-- 20km 储能顶峰 -->
        <line x1="80" y1="120" x2="1140" y2="120" class="grid-line" stroke-dasharray="3 5"/>
        <text x="85" y="114" class="grid-text">20,000m · 重力势能极值蓄能上限 (Ep = max)</text>
        
        <!-- 15km 巡航中继 -->
        <line x1="80" y1="260" x2="1140" y2="260" class="grid-line" />
        <text x="85" y="254" class="grid-text">15,000m · 昼间标准巡航高度</text>

        <!-- 11km 最小功率维持层 -->
        <line x1="80" y1="410" x2="1140" y2="410" class="grid-line" stroke-dasharray="3 5"/>
        <text x="85" y="404" class="grid-text">11,000m · 夜间超长滞空高度 (P_min = 120W)</text>
        
        <!-- 云层顶边界线(防云下断档) -->
        <line x1="80" y1="520" x2="1140" y2="520" stroke="rgba(244, 63, 94, 0.2)" stroke-width="1.2" stroke-dasharray="6 6"/>
        <text x="85" y="514" class="grid-text" fill="rgba(244, 63, 94, 0.6)">7,000m · 稠密云层衰减区 (光伏失效阈值)</text>
      </g>

      <!-- 势能高度等效能量填充面积 -->
      <path id="energyAreaFill" d="" fill="url(#altitudeGradient)" />

      <!-- 24小时循环标准理想航迹曲线 -->
      <path id="trajectoryGuide" class="path-trajectory-glow" d="" />
      <path id="trajectoryPath" class="path-trajectory" d="" />

      <!-- 太阳/月亮复合天体系统 -->
      <g id="celestialBody" transform="translate(600, 80)">
        <!-- 太阳辉光 -->
        <circle id="sunAura" cx="0" cy="0" r="38" fill="rgba(245, 158, 11, 0.15)" filter="url(#solarGlow)" />
        <circle id="sunCore" cx="0" cy="0" r="16" fill="#fbbf24" filter="url(#solarGlow)" />
        <!-- 太阳辐射光线簇 -->
        <g id="sunBeams" opacity="0.6">
          <line x1="0" y1="-26" x2="0" y2="-34" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
          <line x1="18" y1="-18" x2="24" y2="-24" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
          <line x1="26" y1="0" x2="34" y2="0" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
          <line x1="18" y1="18" x2="24" y2="24" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
          <line x1="-18" y1="-18" x2="-24" y2="-24" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
          <line x1="-26" y1="0" x2="-34" y2="0" stroke="#f59e0b" stroke-width="2" stroke-linecap="round"/>
        </g>
        <!-- 月球呈现体 (夜间展示) -->
        <g id="moonGroup" opacity="0">
          <circle cx="0" cy="0" r="14" fill="#cbd5e1" filter="url(#solarGlow)"/>
          <circle cx="5" cy="-3" r="12" fill="#0b1329" />
        </g>
      </g>

      <!-- 光伏吸收光子流束 (太阳 -> 机翼) -->
      <g id="solarPhotonsGroup"></g>

      <!-- 核心主体:6m翼展高空无人机高保真矢量装配体 -->
      <g id="aircraftAssembly" transform="translate(600, 300)">
        
        <!-- 势能反拖气流与能量回收动效指示 -->
        <g id="regenerationAura" opacity="0">
          <ellipse cx="0" cy="0" rx="90" ry="25" fill="none" stroke="var(--accent-emerald)" stroke-width="2" stroke-dasharray="8 6" filter="url(#energyGlow)">
            <animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="5s" repeatCount="indefinite" />
          </ellipse>
        </g>

        <!-- 翼尖涡流微光 -->
        <path d="M -145 0 Q -175 -8 -190 -2" fill="none" stroke="rgba(56, 189, 248, 0.4)" stroke-width="1.5" stroke-linecap="round" />
        <path d="M 145 0 Q 175 -8 190 -2" fill="none" stroke="rgba(56, 189, 248, 0.4)" stroke-width="1.5" stroke-linecap="round" />

        <!-- 6米大展弦比超轻碳纤机翼主体 -->
        <!-- 左机翼 -->
        <path d="M 0 -8 L -140 -2 L -144 4 L 0 5 Z" fill="#1e293b" stroke="#334155" stroke-width="1"/>
        <polygon points="-12,-7 -136,-1 -138,3 -12,4" fill="url(#gaasPattern)" />
        
        <!-- 右机翼 -->
        <path d="M 0 -8 L 140 -2 L 144 4 L 0 5 Z" fill="#1e293b" stroke="#334155" stroke-width="1"/>
        <polygon points="12,-7 136,-1 138,3 12,4" fill="url(#gaasPattern)" />

        <!-- 双尾撑布局机身桁架 -->
        <line x1="-36" y1="4" x2="-36" y2="42" stroke="#475569" stroke-width="2.5" />
        <line x1="36" y1="4" x2="36" y2="42" stroke="#475569" stroke-width="2.5" />

        <!-- V型复合尾翼与全动升降减速板 -->
        <path id="tailElevator" d="M -44 42 L 0 35 L 44 42 L 34 48 L 0 42 L -34 48 Z" fill="#334155" stroke="#64748b" stroke-width="1" />

        <!-- 中央机舱短舱(高比能电池仓 + 超级电容模组) -->
        <ellipse cx="0" cy="0" rx="14" ry="24" fill="#0f172a" stroke="var(--accent-cyan)" stroke-width="1.5" />
        
        <!-- 内部机载储能与四象限电调核心模块指示 -->
        <!-- 1.5kWh锂电组与200F超级电容指示光心 -->
        <circle id="batteryCore" cx="0" cy="4" r="5" fill="var(--accent-emerald)" filter="url(#energyGlow)" />
        <rect id="superCapTag" x="-7" y="-12" width="14" height="4" rx="1" fill="#38bdf8" />

        <!-- 推进/发电一体化无刷电机机舱 -->
        <circle cx="0" cy="-24" r="6" fill="#1e293b" stroke="#64748b" stroke-width="1" />

        <!-- 四象限可变距螺旋桨 -->
        <g id="propellerBlades">
          <ellipse cx="0" cy="-25" rx="22" ry="2.2" fill="rgba(56, 189, 248, 0.7)" />
          <ellipse cx="0" cy="-25" rx="2.2" ry="22" fill="rgba(56, 189, 248, 0.15)" />
        </g>

        <!-- 能量流流动矢量动效线 (机身管道) -->
        <g id="internalEnergyBus">
          <!-- GaAs翼面汇流到电调 -->
          <line x1="-110" y1="0" x2="-5" y2="0" stroke="rgba(245, 158, 11, 0.7)" stroke-width="1.5" stroke-dasharray="3, 3" id="busWingL"/>
          <line x1="110" y1="0" x2="5" y2="0" stroke="rgba(245, 158, 11, 0.7)" stroke-width="1.5" stroke-dasharray="3, 3" id="busWingR"/>
          <!-- 电调与电机双向能量交换通道 (正推 vs 反拖) -->
          <line x1="0" y1="-2" x2="0" y2="-18" stroke="var(--accent-cyan)" stroke-width="2.5" id="busMotor" />
        </g>

        <!-- 机身局部动态标签(精简低扰) -->
        <g transform="translate(0, -36)">
          <rect x="-42" y="-15" width="84" height="15" rx="3" fill="rgba(15, 23, 42, 0.85)" stroke="rgba(56, 189, 248, 0.4)" stroke-width="0.8"/>
          <text id="flightStateTag" x="0" y="-4" fill="#38bdf8" font-size="9" font-weight="600" text-anchor="middle" font-family="var(--font-sans)">正午势能爬升</text>
        </g>
      </g>

      <!-- 关键节点悬浮说明:消除矛盾核心机制(按时间高亮) -->
      <g id="annotationGroup" opacity="0.95">
        <!-- 节点1:势能转换峰值说明 -->
        <g id="noteAscent" transform="translate(680, 150)" opacity="0">
          <line x1="-30" y1="0" x2="-5" y2="0" stroke="var(--accent-emerald)" stroke-width="1"/>
          <circle cx="-5" cy="0" r="2.5" fill="var(--accent-emerald)"/>
          <rect x="0" y="-14" width="168" height="34" rx="4" fill="rgba(13, 22, 38, 0.85)" stroke="var(--accent-emerald)" stroke-width="0.8"/>
          <text x="8" y="0" font-size="10" fill="#a7f3d0" font-weight="600">重力势能储能相 (Ep)</text>
          <text x="8" y="13" font-size="9" fill="#6ee7b7">日间过剩电量 → 换取+9000m高度储备</text>
        </g>

        <!-- 节点2:四象限反拖回充说明 -->
        <g id="noteRegen" transform="translate(740, 290)" opacity="0">
          <line x1="-30" y1="0" x2="-5" y2="0" stroke="var(--accent-gold)" stroke-width="1"/>
          <circle cx="-5" cy="0" r="2.5" fill="var(--accent-gold)"/>
          <rect x="0" y="-14" width="180" height="34" rx="4" fill="rgba(13, 22, 38, 0.85)" stroke="var(--accent-gold)" stroke-width="0.8"/>
          <text x="8" y="0" font-size="10" fill="#fde68a" font-weight="600">下降段四象限发电反拖</text>
          <text x="8" y="13" font-size="9" fill="#fcd34d">势能释放驱动气流风车 → 脉冲充入超级电容</text>
        </g>

        <!-- 节点3:夜间极低功耗维持 -->
        <g id="noteNight" transform="translate(340, 440)" opacity="0">
          <line x1="30" y1="0" x2="5" y2="0" stroke="var(--accent-cyan)" stroke-width="1"/>
          <circle cx="5" cy="0" r="2.5" fill="var(--accent-cyan)"/>
          <rect x="-176" y="-14" width="170" height="34" rx="4" fill="rgba(13, 22, 38, 0.85)" stroke="var(--accent-cyan)" stroke-width="0.8"/>
          <text x="-168" y="0" font-size="10" fill="#bae6fd" font-weight="600">最小功率速度盘旋 (120W)</text>
          <text x="-168" y="13" font-size="9" fill="#7dd3fc">1.5kWh 电池平稳支撑至黎明</text>
        </g>
      </g>
    </svg>

    <!-- 顶部左上角:工程系统信息(极简角标) -->
    <div class="hud-corner hud-top-left">
      <div class="title-tag">
        <span class="pulse-dot"></span>
        <span>SOLAR-GRAVITY HARVESTER · 跨昼夜连续飞行</span>
      </div>
      <div style="font-size: 10px; color: var(--text-muted);">
        翼展 6.0m | GaAs 采光 2.5m² | 势能/超级电容/锂电三级缓冲
      </div>
    </div>

    <!-- 顶部右上角:昼夜仿真时钟与协同状态 -->
    <div class="hud-corner hud-top-right">
      <div class="telemetry-item" style="text-align: right;">
        <span class="telemetry-label">昼夜仿真时钟</span>
        <span class="time-badge" id="hudClock">12:00</span>
      </div>
      <div class="phase-badge" id="hudPhaseName">势能爬升储存相</div>
    </div>

    <!-- 底部控制与高保真遥测总线(贴边不阻挡) -->
    <div class="hud-bottom-bar">
      <!-- 遥测参数阵列 -->
      <div class="telemetry-group">
        <div class="telemetry-item">
          <span class="telemetry-label">巡航高度 ALT</span>
          <span class="telemetry-val" id="valAlt" style="color: #38bdf8;">19,500 m</span>
        </div>
        <div class="telemetry-item">
          <span class="telemetry-label">GaAs 光伏输入</span>
          <span class="telemetry-val" id="valSolar" style="color: #f59e0b;">500 W</span>
        </div>
        <div class="telemetry-item">
          <span class="telemetry-label">推进/发电功率</span>
          <span class="telemetry-val" id="valPower" style="color: #38bdf8;">-360 W</span>
        </div>
        <div class="telemetry-item">
          <span class="telemetry-label">锂电 SOC</span>
          <span class="telemetry-val" id="valSoc" style="color: #10b981;">98 %</span>
        </div>
        <div class="telemetry-item">
          <span class="telemetry-label">电调工作象限</span>
          <span class="telemetry-val" id="valMode" style="color: #a7f3d0;">电机象限 (驱动)</span>
        </div>
      </div>

      <!-- 交互控制组件 -->
      <div class="control-group">
        <div class="slider-container">
          <span>时相调节</span>
          <input type="range" id="timeSlider" min="0" max="24" step="0.05" value="12">
        </div>
        <button class="btn-ctrl" id="btnPlayPause">
          <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
            <path id="playPauseIcon" d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
          </svg>
          <span id="btnPlayText">暂停</span>
        </button>
        <button class="btn-ctrl" id="btnSpeed">1.0x</button>
      </div>
    </div>
  </div>

  <script>
    // ==========================================
    // 物理数学模型与昼夜连续运动动力学
    // ==========================================
    const CONFIG = {
      dayCycleSeconds: 24, // 模拟一个24小时昼夜周期的实际秒数
      viewWidth: 1200,
      viewHeight: 680,
      xMin: 120,
      xMax: 1080,
      altMaxY: 120,    // 对应 20,000m
      altCruiseY: 260, // 对应 15,000m
      altMinY: 410,    // 对应 11,000m
    };

    // 状态全局变量
    let simTimeHours = 12.0; // 0.0 ~ 24.0 (中午 12:00 开始)
    let isPlaying = true;
    let timeScale = 1.0;
    let lastTimestamp = performance.now();

    // DOM 元素缓存
    const stage = document.getElementById('stage');
    const trajectoryPath = document.getElementById('trajectoryPath');
    const trajectoryGuide = document.getElementById('trajectoryGuide');
    const energyAreaFill = document.getElementById('energyAreaFill');
    const celestialBody = document.getElementById('celestialBody');
    const sunCore = document.getElementById('sunCore');
    const sunAura = document.getElementById('sunAura');
    const sunBeams = document.getElementById('sunBeams');
    const moonGroup = document.getElementById('moonGroup');
    const skyStop1 = document.getElementById('skyStop1');
    const skyStop2 = document.getElementById('skyStop2');
    const starField = document.getElementById('starField');
    const aircraft = document.getElementById('aircraftAssembly');
    const propellerBlades = document.getElementById('propellerBlades');
    const flightStateTag = document.getElementById('flightStateTag');
    const batteryCore = document.getElementById('batteryCore');
    const regenerationAura = document.getElementById('regenerationAura');
    const tailElevator = document.getElementById('tailElevator');
    const busMotor = document.getElementById('busMotor');
    const solarPhotonsGroup = document.getElementById('solarPhotonsGroup');

    // 遥测与交互元素
    const hudClock = document.getElementById('hudClock');
    const hudPhaseName = document.getElementById('hudPhaseName');
    const valAlt = document.getElementById('valAlt');
    const valSolar = document.getElementById('valSolar');
    const valPower = document.getElementById('valPower');
    const valSoc = document.getElementById('valSoc');
    const valMode = document.getElementById('valMode');
    const timeSlider = document.getElementById('timeSlider');
    const btnPlayPause = document.getElementById('btnPlayPause');
    const btnPlayText = document.getElementById('btnPlayText');
    const playPauseIcon = document.getElementById('playPauseIcon');
    const btnSpeed = document.getElementById('btnSpeed');

    // 注释节点
    const noteAscent = document.getElementById('noteAscent');
    const noteRegen = document.getElementById('noteRegen');
    const noteNight = document.getElementById('noteNight');

    // 构造连续24小时轨迹函数 (时间 t: 0 -> 24)
    // 06:00 (日出,平飞至爬升) -> 12:00 (正午,攀升至20,000m巅峰重力势能储能)
    // 16:00 (傍晚,太阳衰退,开始以四象限反拖滑翔下降) -> 19:30 (降至11,000m最小功率点)
    // 20:00 - 次日05:30 (深宵极低耗流巡航)
    function getFlightPhysics(hour) {
      const h = (hour % 24 + 24) % 24;
      let x = CONFIG.xMin + (h / 24) * (CONFIG.xMax - CONFIG.xMin);
      let y, altMeters, solarW, motorPowerW, socPercent, modeText, phaseName;
      let isRegen = false;
      let pitchDeg = 0;

      if (h >= 5.5 && h < 12.0) {
        // 清晨光照爬坡 -> 正午攀升蓄势阶段 (重力储能)
        let prog = (h - 5.5) / (12.0 - 5.5);
        // y 从 410 -> 120 (爬升)
        y = CONFIG.altMinY - prog * (CONFIG.altMinY - CONFIG.altMaxY);
        altMeters = Math.round(11000 + prog * (20000 - 11000));
        solarW = Math.round(Math.sin(prog * Math.PI * 0.5) * 500);
        motorPowerW = -Math.round(200 + prog * 180); // 消耗功率爬升
        socPercent = Math.min(99, Math.round(55 + prog * 44));
        modeText = "I 象限 (正向推进爬升)";
        phaseName = "光伏富余 · 势能爬升储存相";
        pitchDeg = -7;
      } else if (h >= 12.0 && h < 15.0) {
        // 正午高空平飞蓄热,满电微调
        let prog = (h - 12.0) / 3.0;
        y = CONFIG.altMaxY + Math.sin(prog * Math.PI) * 12;
        altMeters = Math.round(20000 - Math.sin(prog * Math.PI) * 200);
        solarW = Math.round(480 - prog * 60);
        motorPowerW = -150; // 维持平飞
        socPercent = 99;
        modeText = "I 象限 (高空平飞巡航)";
        phaseName = "势能顶峰 · 电池与电容满载";
        pitchDeg = 0;
      } else if (h >= 15.0 && h < 19.5) {
        // 傍晚光伏衰减 -> 利用重力势能滑翔,电机进入发电机象限反拖回充
        let prog = (h - 15.0) / (19.5 - 15.0);
        // y 从 120 -> 410 (下降)
        y = CONFIG.altMaxY + prog * (CONFIG.altMinY - CONFIG.altMaxY);
        altMeters = Math.round(20000 - prog * (20000 - 11000));
        solarW = Math.max(0, Math.round((1 - prog) * 250));
        // 发电回充: 功率为正 (流入电池)
        motorPowerW = Math.round(160 * Math.sin(prog * Math.PI)); 
        socPercent = Math.round(98 - prog * 4 + (motorPowerW > 100 ? 1 : 0));
        modeText = "IV 象限 (发电机反拖回充)";
        phaseName = "势能回收 · 四象限电调反拖充电";
        isRegen = true;
        pitchDeg = 5;
      } else {
        // 夜间至次日拂晓 (19.5 -> 24/0 -> 5.5):以最小功率速度盘旋 (120W)
        let prog;
        if (h >= 19.5) {
          prog = (h - 19.5) / 10.0;
        } else {
          prog = (h + 4.5) / 10.0;
        }
        y = CONFIG.altMinY + Math.sin(prog * Math.PI * 2) * 8;
        altMeters = Math.round(11000 + Math.sin(prog * Math.PI * 2) * 120);
        solarW = 0;
        motorPowerW = -120; // 最小功率速度点
        socPercent = Math.max(35, Math.round(94 - prog * 58));
        modeText = "I 象限 (最小功率平飞)";
        phaseName = "超长滞空 · 电池低功耗维持相";
        pitchDeg = 1;
      }

      return { x, y, altMeters, solarW, motorPowerW, socPercent, modeText, phaseName, isRegen, pitchDeg };
    }

    // 初始化背景全周期的静态轨迹线
    function buildTrajectorySVG() {
      let pts = [];
      for (let i = 0; i <= 240; i++) {
        let hr = (i / 240) * 24;
        let p = getFlightPhysics(hr);
        pts.push(`${p.x.toFixed(1)},${p.y.toFixed(1)}`);
      }
      const dStr = "M " + pts.join(" L ");
      trajectoryPath.setAttribute("d", dStr);
      trajectoryGuide.setAttribute("d", dStr);

      // 势能高度等效能量填充阴影
      const fillStr = `M ${CONFIG.xMin},${CONFIG.altMinY + 60} L ` + pts.join(" L ") + ` L ${CONFIG.xMax},${CONFIG.altMinY + 60} Z`;
      energyAreaFill.setAttribute("d", fillStr);
    }

    // 太阳光子粒子流系统
    const photons = [];
    const MAX_PHOTONS = 24;
    function initPhotons() {
      for (let i = 0; i < MAX_PHOTONS; i++) {
        const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
        circle.setAttribute("r", "1.8");
        circle.setAttribute("fill", "#fcd34d");
        circle.setAttribute("opacity", "0");
        solarPhotonsGroup.appendChild(circle);
        photons.push({
          elem: circle,
          progress: Math.random(),
          speed: 0.015 + Math.random() * 0.02,
          spreadOffset: (Math.random() - 0.5) * 120
        });
      }
    }

    function updatePhotons(sunX, sunY, planeX, planeY, solarIntensity) {
      if (solarIntensity <= 10) {
        solarPhotonsGroup.style.display = "none";
        return;
      }
      solarPhotonsGroup.style.display = "block";

      photons.forEach(p => {
        p.progress += p.speed;
        if (p.progress > 1) {
          p.progress = 0;
          p.spreadOffset = (Math.random() - 0.5) * 120;
        }

        let currX = sunX + (planeX + p.spreadOffset - sunX) * p.progress;
        let currY = sunY + (planeY - sunY) * p.progress;
        p.elem.setAttribute("cx", currX.toFixed(1));
        p.elem.setAttribute("cy", currY.toFixed(1));
        
        let alpha = Math.sin(p.progress * Math.PI) * (solarIntensity / 500);
        p.elem.setAttribute("opacity", alpha.toFixed(2));
      });
    }

    // 动画帧主渲染循环
    function render(timestamp) {
      const delta = (timestamp - lastTimestamp) / 1000;
      lastTimestamp = timestamp;

      if (isPlaying) {
        const deltaHours = (delta / CONFIG.dayCycleSeconds) * 24 * timeScale;
        simTimeHours = (simTimeHours + deltaHours) % 24;
        timeSlider.value = simTimeHours;
      }

      applySimulationState(simTimeHours);
      requestAnimationFrame(render);
    }

    // 将特定小时的物理模型投射至 SVG 与微型遥测视窗
    function applySimulationState(hour) {
      const state = getFlightPhysics(hour);

      // 1. 更新无人机空间坐标与姿态俯仰角
      aircraft.setAttribute("transform", `translate(${state.x}, ${state.y}) rotate(${state.pitchDeg})`);

      // 2. 动态天空昼夜色系与天体位置计算
      // 太阳天幕弧度 (6:00 从东升起,12:00中天,18:00西落)
      let sunNorm = (hour - 6) / 12; // 0 -> 1
      let sunAngle = sunNorm * Math.PI;
      let sunX = 600 - Math.cos(sunAngle) * 480;
      let sunY = 320 - Math.sin(sunAngle) * 240;
      
      let isDay = (hour >= 5.5 && hour <= 18.5);
      let dayFactor = Math.max(0, Math.sin((hour - 5.5) / 13 * Math.PI));

      if (isDay) {
        celestialBody.setAttribute("transform", `translate(${sunX}, ${sunY})`);
        sunCore.setAttribute("opacity", (dayFactor * 1).toFixed(2));
        sunAura.setAttribute("opacity", (dayFactor * 0.9).toFixed(2));
        sunBeams.setAttribute("opacity", (dayFactor * 0.8).toFixed(2));
        moonGroup.setAttribute("opacity", "0");
        starField.setAttribute("opacity", (0.15 * (1 - dayFactor)).toFixed(2));

        // 湛蓝至暮色自适应渐变
        let r1 = Math.round(4 + dayFactor * 14);
        let g1 = Math.round(7 + dayFactor * 35);
        let b1 = Math.round(20 + dayFactor * 65);
        skyStop1.setAttribute("stop-color", `rgb(${r1},${g1},${b1})`);
        skyStop2.setAttribute("stop-color", `rgb(${Math.round(r1*1.5)},${Math.round(g1*1.6)},${Math.round(b1*1.4)})`);
      } else {
        // 夜间月相升起
        let nightNorm = hour > 18.5 ? (hour - 18.5) / 11 : (hour + 5.5) / 11;
        let moonAngle = nightNorm * Math.PI;
        let moonX = 600 - Math.cos(moonAngle) * 440;
        let moonY = 320 - Math.sin(moonAngle) * 220;

        celestialBody.setAttribute("transform", `translate(${moonX}, ${moonY})`);
        sunCore.setAttribute("opacity", "0");
        sunAura.setAttribute("opacity", "0");
        sunBeams.setAttribute("opacity", "0");
        moonGroup.setAttribute("opacity", "0.95");
        starField.setAttribute("opacity", "0.85");

        skyStop1.setAttribute("stop-color", "#02040a");
        skyStop2.setAttribute("stop-color", "#070c1a");
      }

      // 3. 光子雨束驱动
      updatePhotons(sunX, sunY, state.x, state.y - 10, state.solarW);

      // 4. 四象限电调与推进发电动效切换
      if (state.isRegen) {
        // 反拖发电模式:绿色能量波纹高亮,气流倒灌螺旋桨回充
        regenerationAura.setAttribute("opacity", "0.9");
        batteryCore.setAttribute("fill", "var(--accent-gold)");
        busMotor.setAttribute("stroke", "var(--accent-gold)");
        tailElevator.setAttribute("transform", "rotate(-6, 0, 40)"); // 减速板张开配合回收
        flightStateTag.textContent = "重力势能反拖发电 (+160W)";
        flightStateTag.setAttribute("fill", "var(--accent-gold)");
      } else {
        regenerationAura.setAttribute("opacity", "0");
        batteryCore.setAttribute("fill", state.socPercent > 80 ? "var(--accent-emerald)" : "var(--accent-cyan)");
        busMotor.setAttribute("stroke", "var(--accent-cyan)");
        tailElevator.setAttribute("transform", "rotate(0, 0, 40)");
        
        if (state.solarW > 250) {
          flightStateTag.textContent = "GaAs 光电快速蓄能";
          flightStateTag.setAttribute("fill", "var(--accent-cyan)");
        } else if (hour < 5.5 || hour >= 19.5) {
          flightStateTag.textContent = "低耗盘旋 (120W维持)";
          flightStateTag.setAttribute("fill", "#94a3b8");
        } else {
          flightStateTag.textContent = "巡航自持飞行";
          flightStateTag.setAttribute("fill", "var(--accent-cyan)");
        }
      }

      // 螺旋桨转速响应
      let propRot = (performance.now() * (state.isRegen ? 0.35 : 1.2)) % 360;
      propellerBlades.setAttribute("transform", `rotate(${propRot}, 0, -25)`);

      // 5. 关键原理解释卡片淡入/淡出控制(避免视觉遮挡,靠近时才显现)
      noteAscent.setAttribute("opacity", (hour >= 9.0 && hour <= 13.5) ? "1" : "0.08");
      noteRegen.setAttribute("opacity", (hour >= 15.5 && hour <= 19.0) ? "1" : "0.08");
      noteNight.setAttribute("opacity", (hour >= 21.0 || hour <= 4.0) ? "1" : "0.08");

      // 6. 遥测面板数值同步
      let hh = Math.floor(hour);
      let mm = Math.floor((hour - hh) * 60);
      hudClock.textContent = `${String(hh).padStart(2, '0')}:${String(mm).padStart(2, '0')}`;
      hudPhaseName.textContent = state.phaseName;

      valAlt.textContent = `${state.altMeters.toLocaleString()} m`;
      valSolar.textContent = `${state.solarW} W`;
      valPower.textContent = `${state.motorPowerW > 0 ? '+' : ''}${state.motorPowerW} W`;
      valPower.style.color = state.motorPowerW > 0 ? "var(--accent-gold)" : (state.motorPowerW < -180 ? "#38bdf8" : "#94a3b8");
      valSoc.textContent = `${state.socPercent} %`;
      valSoc.style.color = state.socPercent > 50 ? "var(--accent-emerald)" : "var(--accent-rose)";
      valMode.textContent = state.modeText;
    }

    // ==========================================
    // 交互响应与自动循环机制
    // ==========================================
    timeSlider.addEventListener('input', (e) => {
      simTimeHours = parseFloat(e.target.value);
      applySimulationState(simTimeHours);
    });

    btnPlayPause.addEventListener('click', () => {
      isPlaying = !isPlaying;
      btnPlayText.textContent = isPlaying ? "暂停" : "播放";
      playPauseIcon.setAttribute("d", isPlaying ? "M6 19h4V5H6v14zm8-14v14h4V5h-4z" : "M8 5v14l11-7z");
    });

    const speedOptions = [0.5, 1.0, 2.0, 4.0];
    let speedIdx = 1;
    btnSpeed.addEventListener('click', () => {
      speedIdx = (speedIdx + 1) % speedOptions.length;
      timeScale = speedOptions[speedIdx];
      btnSpeed.textContent = timeScale.toFixed(1) + 'x';
    });

    // 页面加载完成后自启动运行
    window.addEventListener('DOMContentLoaded', () => {
      buildTrajectorySVG();
      initPhotons();
      applySimulationState(simTimeHours);
      lastTimestamp = performance.now();
      requestAnimationFrame(render);
    });
  </script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>跨昼夜太阳能飞行器能量自持系统 (IFR 原理仿真)</title>
  <style>
    :root {
      --bg-dark: #070b14;
      --panel-bg: rgba(13, 22, 41, 0.75);
      --border-line: rgba(70, 110, 170, 0.25);
      --accent-cyan: #00f0ff;
      --accent-green: #10ff98;
      --accent-gold: #ffb800;
      --accent-orange: #ff5d22;
      --accent-blue: #2c7bf6;
      --font-display: 'Rajdhani', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      --font-mono: 'JetBrains Mono', 'Fira Code', monospace;
    }

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      user-select: none;
    }

    body {
      background-color: var(--bg-dark);
      color: #e2e8f0;
      font-family: var(--font-display);
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      overflow: hidden;
      background-image: 
        radial-gradient(circle at 50% 20%, rgba(20, 45, 90, 0.4) 0%, transparent 60%),
        radial-gradient(circle at 80% 90%, rgba(10, 30, 60, 0.6) 0%, transparent 50%);
    }

    .simulation-container {
      position: relative;
      width: 1200px;
      max-width: 98vw;
      height: 760px;
      max-height: 96vh;
      background: var(--panel-bg);
      border: 1px solid var(--border-line);
      border-radius: 16px;
      backdrop-filter: blur(20px);
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 1px 1px rgba(255, 255, 255, 0.05);
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    /* 顶部仪表条 */
    .header-bar {
      height: 58px;
      border-bottom: 1px solid var(--border-line);
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0 24px;
      background: rgba(8, 14, 28, 0.6);
    }

    .title-group {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .ifr-badge {
      font-size: 11px;
      font-weight: 700;
      padding: 3px 8px;
      border-radius: 4px;
      background: linear-gradient(135deg, rgba(0, 240, 255, 0.2), rgba(16, 255, 152, 0.2));
      color: var(--accent-cyan);
      border: 1px solid rgba(0, 240, 255, 0.35);
      letter-spacing: 0.5px;
    }

    .main-title {
      font-size: 18px;
      font-weight: 600;
      letter-spacing: 0.8px;
      color: #fff;
    }

    .sub-meta {
      font-size: 13px;
      color: #7b8ea8;
      font-family: var(--font-mono);
    }

    /* 中间核心 SVG 画布区 */
    .viewport {
      flex: 1;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    svg#flightCanvas {
      width: 100%;
      height: 100%;
      display: block;
    }

    /* 底部交互控制区 */
    .control-deck {
      height: 90px;
      border-top: 1px solid var(--border-line);
      background: rgba(9, 15, 28, 0.8);
      display: grid;
      grid-template-columns: 180px 1fr 340px;
      align-items: center;
      padding: 0 24px;
      gap: 20px;
    }

    .play-controls {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .btn {
      background: rgba(255, 255, 255, 0.05);
      border: 1px solid rgba(255, 255, 255, 0.15);
      color: #e2e8f0;
      padding: 7px 16px;
      border-radius: 6px;
      cursor: pointer;
      font-size: 13px;
      font-weight: 500;
      transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 6px;
    }

    .btn:hover {
      background: rgba(0, 240, 255, 0.15);
      border-color: var(--accent-cyan);
      color: #fff;
      transform: translateY(-1px);
    }

    .timeline-wrapper {
      display: flex;
      flex-direction: column;
      gap: 6px;
    }

    .timeline-labels {
      display: flex;
      justify-content: space-between;
      font-size: 12px;
      font-family: var(--font-mono);
      color: #7b8ea8;
    }

    .timeline-slider {
      width: 100%;
      -webkit-appearance: none;
      appearance: none;
      height: 6px;
      border-radius: 3px;
      background: linear-gradient(90deg, 
        #0f172a 0%, 
        #ff9d00 25%, 
        #ffdd00 48%, 
        #3b82f6 68%, 
        #0a1128 100%
      );
      outline: none;
      cursor: pointer;
    }

    .timeline-slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 18px;
      height: 18px;
      border-radius: 50%;
      background: #fff;
      border: 2px solid var(--accent-cyan);
      box-shadow: 0 0 12px var(--accent-cyan);
      cursor: pointer;
      transition: transform 0.1s ease;
    }

    .timeline-slider::-webkit-slider-thumb:hover {
      transform: scale(1.2);
    }

    /* 实时遥测指标 */
    .telemetry-strip {
      display: flex;
      justify-content: space-between;
      gap: 12px;
    }

    .telemetry-item {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
    }

    .telem-tag {
      font-size: 11px;
      color: #64748b;
      text-transform: uppercase;
      font-family: var(--font-mono);
    }

    .telem-val {
      font-size: 15px;
      font-weight: 700;
      font-family: var(--font-mono);
      color: #f8fafc;
    }

    .val-highlight-pv { color: var(--accent-gold); }
    .val-highlight-rec { color: var(--accent-green); }
    .val-highlight-bat { color: var(--accent-cyan); }

    /* SVG 内部动效与滤镜 */
    .flight-path-bg {
      stroke: rgba(255, 255, 255, 0.08);
      stroke-dasharray: 4 4;
    }

    .flight-path-active {
      stroke-dasharray: 8 6;
      animation: dashMove 30s linear infinite;
    }

    @keyframes dashMove {
      to { stroke-dashoffset: -1000; }
    }
  </style>
</head>
<body>

  <div class="simulation-container">
    <!-- 顶部状态栏 -->
    <header class="header-bar">
      <div class="title-group">
        <span class="ifr-badge">TRIZ 最终理想解 (IFR)</span>
        <h1 class="main-title">6m 级高空长航时太阳能无人机 · 跨昼夜闭环能量自持系统</h1>
      </div>
      <div class="sub-meta">
        <span id="cyclePhase">状态:日出光伏爬坡储能</span> | 
        <span>自持率:100% 无断档</span>
      </div>
    </header>

    <!-- 中部主交互/动画画布 -->
    <main class="viewport">
      <svg id="flightCanvas" viewBox="0 0 1200 600" preserveAspectRatio="xMidYMid meet">
        <defs>
          <!-- 发光滤镜 -->
          <filter id="glow-cyan" x="-30%" y="-30%" width="160%" height="160%">
            <feGaussianBlur stdDeviation="5" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>

          <filter id="glow-green" x="-30%" y="-30%" width="160%" height="160%">
            <feGaussianBlur stdDeviation="6" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>

          <filter id="glow-gold" x="-30%" y="-30%" width="160%" height="160%">
            <feGaussianBlur stdDeviation="6" result="blur" />
            <feMerge>
              <feMergeNode in="blur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>

          <!-- 天空昼夜渐变背景 -->
          <linearGradient id="skyGrad" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stop-color="#050811" />
            <stop offset="20%" stop-color="#141829" />
            <stop offset="35%" stop-color="#ff7b39" stop-opacity="0.25" />
            <stop offset="50%" stop-color="#1e3a70" stop-opacity="0.35" />
            <stop offset="68%" stop-color="#4c2642" stop-opacity="0.3" />
            <stop offset="85%" stop-color="#0a101f" />
            <stop offset="100%" stop-color="#050811" />
          </linearGradient>

          <!-- 高度网格梯度 -->
          <linearGradient id="altGrad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stop-color="#00f0ff" stop-opacity="0.08" />
            <stop offset="100%" stop-color="#00f0ff" stop-opacity="0.0" />
          </linearGradient>

          <!-- 能量箭头 Marker -->
          <marker id="arrow-green" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
            <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#10ff98"/>
          </marker>
          <marker id="arrow-gold" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
            <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#ffb800"/>
          </marker>
          <marker id="arrow-cyan" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
            <path d="M 0 1.5 L 8 5 L 0 8.5 z" fill="#00f0ff"/>
          </marker>
        </defs>

        <!-- 背景昼夜色彩幕布 -->
        <rect x="0" y="0" width="1200" height="420" fill="url(#skyGrad)" opacity="0.9" />

        <!-- 纵向高度网格线 (标示高度势能储能) -->
        <g opacity="0.4" font-size="10" fill="#64748b" font-family="monospace">
          <line x1="80" y1="60" x2="1140" y2="60" stroke="#334155" stroke-dasharray="2 4" />
          <text x="85" y="55">高空储能顶峰 8,000 m (最大势能位)</text>
          
          <line x1="80" y1="160" x2="1140" y2="160" stroke="#334155" stroke-dasharray="2 4" />
          <text x="85" y="155">巡航能量平衡线 5,000 m</text>
          
          <line x1="80" y1="280" x2="1140" y2="280" stroke="#334155" stroke-dasharray="2 4" />
          <text x="85" y="275">夜间最小阻力巡航高度 2,500 m</text>

          <line x1="80" y1="360" x2="1140" y2="360" stroke="#1e293b" />
          <text x="85" y="355">云层参考顶高 1,800 m</text>
        </g>

        <!-- 24小时飞行轨迹曲线 (展现: 爬升储能 -> 下降反拖发电 -> 夜间低速巡航) -->
        <!-- 路径数据: 从 0h (x=80) 到 24h (x=1140) -->
        <path id="flightTrajectory" 
              d="M 80,280 C 220,280 320,270 420,190 C 490,130 550,60 620,60 C 700,60 760,110 820,250 C 870,300 940,280 1140,280" 
              fill="none" 
              stroke="#00f0ff" 
              stroke-width="2.5" 
              opacity="0.8" 
              filter="url(#glow-cyan)"/>
        
        <!-- 飞行轨迹投影填充 (高度势能可视化) -->
        <path d="M 80,280 C 220,280 320,270 420,190 C 490,130 550,60 620,60 C 700,60 760,110 820,250 C 870,300 940,280 1140,280 L 1140,360 L 80,360 Z" 
              fill="url(#altGrad)" />

        <!-- 关键相位解说气泡 (随核心原理点分布) -->
        <g id="annotations" font-size="11" font-family="sans-serif">
          <!-- 正午爬升段 -->
          <g transform="translate(560, 40)">
            <rect x="-90" y="-22" width="180" height="26" rx="4" fill="rgba(10,25,50,0.85)" stroke="#ffb800" stroke-width="1"/>
            <text x="0" y="-5" fill="#ffdd55" text-anchor="middle" font-weight="600">正午太阳能过剩 ➔ 爬升蓄重力势能</text>
          </g>

          <!-- 傍晚反拖发电段 (IFR核心亮点) -->
          <g transform="translate(810, 160)">
            <rect x="-115" y="-26" width="230" height="36" rx="4" fill="rgba(6,35,30,0.9)" stroke="#10ff98" stroke-width="1.2" filter="url(#glow-green)"/>
            <text x="0" y="-8" fill="#10ff98" text-anchor="middle" font-weight="700">★ 势能回收:电机四象限反拖发电</text>
            <text x="0" y="6" fill="#a7f3d0" text-anchor="middle" font-size="10">升降舵阻力配平 · 升压回充超电容与电池</text>
            <line x1="-30" y1="12" x2="0" y2="45" stroke="#10ff98" stroke-width="1.5" stroke-dasharray="2 3"/>
          </g>

          <!-- 夜间最小功率段 -->
          <g transform="translate(1010, 240)">
            <rect x="-85" y="-22" width="170" height="26" rx="4" fill="rgba(15,23,42,0.85)" stroke="#38bdf8" stroke-width="1"/>
            <text x="0" y="-5" fill="#38bdf8" text-anchor="middle">夜间最小功率点盘旋 (120W)</text>
          </g>
        </g>

        <!-- 实时无人机实体 (将在 JS 中由路径位置更新 transform) -->
        <g id="uavGroup" transform="translate(80, 280)">
          <!-- 动态能量光环 -->
          <ellipse id="uavAura" cx="0" cy="0" rx="35" ry="18" fill="rgba(0, 240, 255, 0.15)" filter="url(#glow-cyan)" />
          
          <!-- 6m展弦比高空无人机简图 (俯仰俯视微仰角矢量) -->
          <g id="uavAirframe">
            <!-- 机翼 (铺设GaAs光伏阵列) -->
            <path d="M -55,-2 L 0,-6 L 55,-2 L 50,3 L 0,1 L -50,3 Z" fill="#1e293b" stroke="#00f0ff" stroke-width="1.2" />
            <!-- 光伏阵列薄膜质感纹理 (GaAs高效率蓝金色栅格) -->
            <line x1="-48" y1="-1" x2="-8" y2="-4" stroke="#ffb800" stroke-width="2.5" opacity="0.9" id="solarWingL" />
            <line x1="8" y1="-4" x2="48" y2="-1" stroke="#ffb800" stroke-width="2.5" opacity="0.9" id="solarWingR" />
            <!-- 机身与动力舱 -->
            <path d="M 0,-15 L 4,-2 L 3,18 L -3,18 L -4,-2 Z" fill="#0f172a" stroke="#94a3b8" stroke-width="1" />
            <!-- V型尾翼兼阻力减速板 -->
            <path d="M -14,24 L 0,16 L 14,24" fill="none" stroke="#38bdf8" stroke-width="1.8" id="elevatorRudder" />
            <!-- 螺旋桨 / 能量回收反拖发电机 -->
            <g id="propellerGroup" transform="translate(0, -15)">
              <line x1="-16" y1="0" x2="16" y2="0" stroke="#fff" stroke-width="2" opacity="0.8" id="propBlade" />
              <circle cx="0" cy="0" r="2.5" fill="#10ff98" />
            </g>
          </g>

          <!-- 动态能量流向指示箭头/粒子 (悬浮在飞机上方) -->
          <g id="flightEnergyVectors" transform="translate(0, -32)">
            <!-- 光伏输入流 (向下注入机身) -->
            <path id="pvFlowVec" d="M 0,-15 L 0, -2" stroke="#ffb800" stroke-width="3" marker-end="url(#arrow-gold)" opacity="1" />
            <!-- 势能反拖流 (螺旋桨往电池回灌) -->
            <path id="regenFlowVec" d="M 12,-12 L 0, 0" stroke="#10ff98" stroke-width="3" marker-end="url(#arrow-green)" opacity="0" filter="url(#glow-green)" />
          </g>
        </g>

        <!-- 下半部分:核心能量架构与四象限电调原理展开窗口 (430px - 590px) -->
        <g transform="translate(50, 420)">
          <!-- 架构底板 -->
          <rect x="0" y="0" width="1100" height="165" rx="8" fill="rgba(8, 16, 32, 0.95)" stroke="rgba(70, 110, 170, 0.4)" stroke-width="1.2" />
          
          <text x="24" y="24" font-size="13" font-weight="700" fill="#cbd5e1" letter-spacing="1">
            ⚡ 核心机理:四象限能量流动与混合储能拓扑 (IFR 无耗散转换)
          </text>

          <!-- 模块 1: GaAs 薄膜太阳能 (2.5m², 500Wp) -->
          <g transform="translate(35, 45)">
            <rect x="0" y="0" width="180" height="95" rx="6" fill="#0f1f38" stroke="#ffb800" stroke-width="1.2" />
            <text x="14" y="26" font-size="12" font-weight="700" fill="#ffb800">GaAs 柔性光伏阵列</text>
            <text x="14" y="46" font-size="11" fill="#94a3b8">采光面积:2.5 m² (28%)</text>
            <text x="14" y="65" font-size="11" fill="#94a3b8">输出工况:<tspan id="archPvPower" fill="#ffdd55" font-weight="bold">480 W</tspan></text>
            <text x="14" y="82" font-size="10" fill="#64748b">白天全额供电并充能</text>
          </g>

          <!-- 流线 1: 光伏到母线 -->
          <path id="linePvBus" d="M 215,92 L 285,92" stroke="#ffb800" stroke-width="2.5" marker-end="url(#arrow-gold)" stroke-dasharray="4 2" />

          <!-- 模块 2: 双向智能能量管理中枢 (EMS & 四象限调速器) -->
          <g transform="translate(295, 38)">
            <rect x="0" y="0" width="230" height="110" rx="6" fill="#0b2444" stroke="#00f0ff" stroke-width="1.5" filter="url(#glow-cyan)" />
            <text x="16" y="24" font-size="12" font-weight="700" fill="#00f0ff">智能前馈 EMS & 4-Quadrant ESC</text>
            <text x="16" y="45" font-size="11" fill="#cbd5e1">当前运行象限:<tspan id="escMode" fill="#10ff98" font-weight="bold">I 象限 (正向电动)</tspan></text>
            <text x="16" y="66" font-size="10" fill="#94a3b8">前馈依据:光伏预测 ➔ SOC ➔ 航迹</text>
            <text x="16" y="86" font-size="10" fill="#94a3b8">换流状态:升压斩波回充模式</text>
            <circle cx="210" cy="20" r="5" id="escStatusLight" fill="#00f0ff" />
          </g>

          <!-- 流线 2: EMS 与 储能系统双向交互 -->
          <path id="lineBusStorage" d="M 525,82 L 595,82" stroke="#00f0ff" stroke-width="2.5" marker-end="url(#arrow-cyan)" stroke-dasharray="4 2" />
          <path id="lineStorageBus" d="M 595,102 L 525,102" stroke="#38bdf8" stroke-width="2" marker-end="url(#arrow-cyan)" stroke-dasharray="4 2" opacity="0.3" />

          <!-- 模块 3: 高比能混合储能矩阵 (1.5kWh 锂电 + 200F 超电容) -->
          <g transform="translate(605, 45)">
            <rect x="0" y="0" width="220" height="95" rx="6" fill="#0f1f38" stroke="#00f0ff" stroke-width="1.2" />
            <text x="14" y="26" font-size="12" font-weight="700" fill="#38bdf8">1.5kWh 锂电 + 200F 超级电容</text>
            <!-- SOC 条 -->
            <rect x="14" y="38" width="190" height="10" rx="3" fill="#1e293b" />
            <rect id="socBar" x="14" y="38" width="160" height="10" rx="3" fill="#10ff98" />
            <text x="14" y="66" font-size="11" fill="#94a3b8">电池 SOC:<tspan id="archSocVal" fill="#10ff98" font-weight="bold">84%</tspan></text>
            <text x="14" y="84" font-size="10" fill="#64748b">超电容瞬态平抑 · 夜间支持 11h+</text>
          </g>

          <!-- 流线 3: 动力输出与反拖回流 -->
          <path id="lineDriveMotor" d="M 410,148 L 410,165" stroke="#00f0ff" stroke-width="2" />
          <path id="lineMotorRegen" d="M 875,92 L 525,92" stroke="#10ff98" stroke-width="3" marker-end="url(#arrow-green)" stroke-dasharray="6 3" opacity="0" id="regenPowerCable" />

          <!-- 模块 4: 高效无刷电机 & 变距旋翼 (发电/驱动双模) -->
          <g transform="translate(875, 45)">
            <rect id="motorBox" x="0" y="0" width="195" height="95" rx="6" fill="#0f1f38" stroke="#38bdf8" stroke-width="1.2" />
            <text x="14" y="26" font-size="12" font-weight="700" fill="#38bdf8">BLDC 推进/反拖发电单元</text>
            <text x="14" y="46" font-size="11" fill="#94a3b8">机械工作态:<tspan id="propStateText" fill="#38bdf8" font-weight="bold">高效推进模式</tspan></text>
            <text x="14" y="65" font-size="11" fill="#94a3b8">轴功率:<tspan id="shaftPower" fill="#f8fafc" font-weight="bold">150 W</tspan></text>
            <text x="14" y="82" font-size="10" fill="#64748b">下降段利用风车效应反拖发电</text>
          </g>
        </g>
      </svg>
    </main>

    <!-- 底部控制面板 -->
    <footer class="control-deck">
      <div class="play-controls">
        <button class="btn" id="btnTogglePlay">
          <span id="playIcon">⏸</span> <span id="playText">暂停</span>
        </button>
        <button class="btn" id="btnReset">
          <span>↺</span> 重播
        </button>
      </div>

      <div class="timeline-wrapper">
        <div class="timeline-labels">
          <span>00:00 (拂晓)</span>
          <span>06:00 (日出)</span>
          <span>12:00 (正午爬升)</span>
          <span>18:00 (暮色滑翔发电)</span>
          <span>24:00 (子夜巡航)</span>
        </div>
        <input type="range" id="timeSlider" class="timeline-slider" min="0" max="24" step="0.05" value="7">
      </div>

      <div class="telemetry-strip">
        <div class="telemetry-item">
          <span class="telem-tag">光伏功率 (PV)</span>
          <span class="telem-val val-highlight-pv" id="valPv">380 W</span>
        </div>
        <div class="telemetry-item">
          <span class="telem-tag">势能回收功率</span>
          <span class="telem-val val-highlight-rec" id="valRegen">0 W</span>
        </div>
        <div class="telemetry-item">
          <span class="telem-tag">储能 SOC</span>
          <span class="telem-val val-highlight-bat" id="valSoc">92%</span>
        </div>
        <div class="telemetry-item">
          <span class="telem-tag">飞行高度</span>
          <span class="telem-val" id="valAlt">4,200 m</span>
        </div>
      </div>
    </footer>
  </div>

  <script>
    // 跨昼夜持续飞行与势能回收物理数学模型
    const TrajectoryModel = {
      // 0h ~ 24h 时间映射与物理推导
      calculateState(t) {
        // t: 0 to 24 (小时)
        let altitude = 0; // 米
        let pvPower = 0;  // 瓦特 (GaAs 2.5m², 峰值 ~500W)
        let motorPower = 0; // 推进功耗为正,反拖发电为负
        let regenPower = 0; // 回充功率 (W)
        let phaseDesc = '';
        let escMode = '';
        let isRegenerating = false;

        // 1. 光照与光伏发电计算 (6:00 日出, 12:00 达峰 500W, 18:30 日落)
        if (t >= 6.0 && t <= 18.5) {
          const sunAngle = ((t - 6.0) / 12.5) * Math.PI;
          pvPower = Math.max(0, Math.sin(sunAngle) * 510);
        } else {
          pvPower = 0;
        }

        // 2. 高度剖面与重力势能调度计算
        // 0-6h: 2500m 夜间平飞
        // 6-12h: 光伏爬坡,富余能量转换为高度势能,爬升至 8000m
        // 12-14h: 高空 8000m 极目巡航储能
        // 14-18h: 暮色下降,重力势能反拖发电,滑降至 2500m
        // 18-24h: 2500m 最小功率速度盘旋 (120W)
        if (t < 6.0) {
          altitude = 2500;
          motorPower = 120; // 最小功率速度点
          phaseDesc = "夜间:极小功率点盘旋维持 (120W)";
          escMode = "I 象限 (超低能耗驱动)";
        } else if (t < 13.0) {
          // 爬升段: 2500 -> 8000
          const progress = (t - 6.0) / 7.0;
          altitude = 2500 + 5500 * Math.sin(progress * Math.PI * 0.5);
          motorPower = 280; // 爬升消耗额外功率
          phaseDesc = "上午至正午:富余光伏爬升 · 转化为重力势能储能";
          escMode = "I 象限 (大推力爬升驱动)";
        } else if (t < 14.5) {
          altitude = 8000;
          motorPower = 150;
          phaseDesc = "正午顶峰:高空 8,000m 势能高位锁定 · 电池饱和充至95%+";
          escMode = "I 象限 (高空巡航驱动)";
        } else if (t < 18.5) {
          // 核心 IFR 机制:下降反拖发电段 8000 -> 2500m
          const prog = (t - 14.5) / 4.0;
          altitude = 8000 - 5500 * (1 - Math.cos(prog * Math.PI * 0.5));
          // 重力势能下落释放速率: m*g*Δh / Δt, 结合四象限回充效率约 65%
          isRegenerating = true;
          regenPower = 240 * Math.sin(prog * Math.PI); // 峰值达 240W 反拖回充
          motorPower = -regenPower; // 处于第四象限发电机态
          phaseDesc = "★ 傍晚关键段:受控俯冲 · 四象限电调反拖发电回充超电容";
          escMode = "IV 象限 (发电机反拖回充)";
        } else {
          altitude = 2500;
          motorPower = 120; // 夜间最小功率
          phaseDesc = "入夜:电池平稳接管 · 最小阻力速度盘旋自持";
          escMode = "I 象限 (低功耗巡航驱动)";
        }

        // 3. SOC 电池电量状态估计模型 (初始约 60%, 白天充到 95%, 傍晚势能回收补偿, 夜间消耗)
        let soc = 0.65;
        if (t <= 6.0) {
          soc = 0.65 - (t / 6.0) * 0.25; // 65% 降到 40%
        } else if (t <= 14.5) {
          const p = (t - 6.0) / 8.5;
          soc = 0.40 + p * 0.56; // 充到 96%
        } else if (t <= 18.5) {
          // 势能回充维持高位,几乎不掉电反而微涨或平持
          soc = 0.96 - ((t - 14.5) / 4.0) * 0.04 + (regenPower / 1000) * 0.05;
        } else {
          // 夜间平缓消耗
          soc = 0.94 - ((t - 18.5) / 5.5) * 0.29; // 到拂晓降回 65% 形成完美闭环!
        }

        return {
          t,
          altitude: Math.round(altitude),
          pvPower: Math.round(pvPower),
          motorPower: Math.round(motorPower),
          regenPower: Math.round(regenPower),
          soc: Math.max(10, Math.min(99, Math.round(soc * 100))),
          phaseDesc,
          escMode,
          isRegenerating
        };
      }
    };

    // 交互与渲染引擎
    class SimulationApp {
      constructor() {
        this.svg = document.getElementById('flightCanvas');
        this.flightPath = document.getElementById('flightTrajectory');
        this.uavGroup = document.getElementById('uavGroup');
        this.timeSlider = document.getElementById('timeSlider');
        this.btnTogglePlay = document.getElementById('btnTogglePlay');
        this.btnReset = document.getElementById('btnReset');
        this.playText = document.getElementById('playText');
        this.playIcon = document.getElementById('playIcon');

        // 遥测面板 DOM
        this.valPv = document.getElementById('valPv');
        this.valRegen = document.getElementById('valRegen');
        this.valSoc = document.getElementById('valSoc');
        this.valAlt = document.getElementById('valAlt');
        this.cyclePhase = document.getElementById('cyclePhase');

        // SVG 内部拓扑 DOM
        this.archPvPower = document.getElementById('archPvPower');
        this.archSocVal = document.getElementById('archSocVal');
        this.socBar = document.getElementById('socBar');
        this.escMode = document.getElementById('escMode');
        this.escStatusLight = document.getElementById('escStatusLight');
        this.propStateText = document.getElementById('propStateText');
        this.shaftPower = document.getElementById('shaftPower');
        this.regenPowerCable = document.getElementById('regenPowerCable');
        this.regenFlowVec = document.getElementById('regenFlowVec');
        this.pvFlowVec = document.getElementById('pvFlowVec');
        this.solarWingL = document.getElementById('solarWingL');
        this.solarWingR = document.getElementById('solarWingR');
        this.propBlade = document.getElementById('propBlade');
        this.elevatorRudder = document.getElementById('elevatorRudder');

        this.currentTime = 7.0; // 默认早晨 7 点自启动
        this.isPlaying = true;
        this.simSpeed = 0.8; // 小时/秒
        this.lastTimestamp = null;
        this.pathLength = this.flightPath.getTotalLength();

        this.initEventListeners();
        this.startLoop();
      }

      initEventListeners() {
        this.btnTogglePlay.addEventListener('click', () => {
          this.isPlaying = !this.isPlaying;
          this.updatePlayBtn();
        });

        this.btnReset.addEventListener('click', () => {
          this.currentTime = 6.0;
          this.isPlaying = true;
          this.updatePlayBtn();
        });

        this.timeSlider.addEventListener('input', (e) => {
          this.currentTime = parseFloat(e.target.value);
          this.render();
        });
      }

      updatePlayBtn() {
        if (this.isPlaying) {
          this.playIcon.textContent = '⏸';
          this.playText.textContent = '暂停';
        } else {
          this.playIcon.textContent = '▶';
          this.playText.textContent = '播放';
        }
      }

      startLoop() {
        const loop = (timestamp) => {
          if (!this.lastTimestamp) this.lastTimestamp = timestamp;
          const dt = (timestamp - this.lastTimestamp) / 1000;
          this.lastTimestamp = timestamp;

          if (this.isPlaying) {
            this.currentTime += dt * this.simSpeed;
            if (this.currentTime >= 24) {
              this.currentTime = 0; // 跨昼夜无缝闭环循环
            }
            this.timeSlider.value = this.currentTime;
            this.render();
          }

          // 旋翼旋转高频动效
          const propRotation = (timestamp * 1.5) % 360;
          if (this.propBlade) {
            this.propBlade.setAttribute('transform', `rotate(${propRotation})`);
          }

          requestAnimationFrame(loop);
        };
        requestAnimationFrame(loop);
      }

      render() {
        const state = TrajectoryModel.calculateState(this.currentTime);

        // 1. 更新无人机在航迹曲线上的物理空间位置与姿态
        const normT = this.currentTime / 24.0;
        const currentDistance = normT * this.pathLength;
        const pt = this.flightPath.getPointAtLength(currentDistance);
        
        // 计算航向俯仰角 (切线角)
        const nextPt = this.flightPath.getPointAtLength(Math.min(this.pathLength, currentDistance + 2));
        const angle = Math.atan2(nextPt.y - pt.y, nextPt.x - pt.x) * (180 / Math.PI);

        this.uavGroup.setAttribute('transform', `translate(${pt.x}, ${pt.y}) rotate(${angle * 0.7})`);

        // 2. 更新仪表与文本数据
        this.valPv.textContent = `${state.pvPower} W`;
        this.valRegen.textContent = `${state.regenPower} W`;
        this.valSoc.textContent = `${state.soc} %`;
        this.valAlt.textContent = `${state.altitude.toLocaleString()} m`;
        this.cyclePhase.textContent = `状态:${state.phaseDesc}`;

        // 3. 架构拓扑状态同步
        this.archPvPower.textContent = `${state.pvPower} W`;
        this.archSocVal.textContent = `${state.soc}%`;
        this.socBar.setAttribute('width', (state.soc / 100) * 190);
        this.escMode.textContent = state.escMode;

        // 4. 关键四象限反拖发电视觉特效 (IFR 核心展示)
        if (state.isRegenerating) {
          // 下降反拖发电工况:荧光绿脉冲高亮
          this.escStatusLight.setAttribute('fill', '#10ff98');
          this.propStateText.textContent = '风车反拖发电态 (IV象限)';
          this.propStateText.setAttribute('fill', '#10ff98');
          this.shaftPower.textContent = `+${state.regenPower} W (回充功率)`;
          this.shaftPower.setAttribute('fill', '#10ff98');
          
          this.regenPowerCable.setAttribute('opacity', '1');
          this.regenFlowVec.setAttribute('opacity', '1');
          this.elevatorRudder.setAttribute('stroke', '#10ff98'); // 阻力板配平
        } else {
          // 普通驱动或夜间巡航工况
          this.escStatusLight.setAttribute('fill', state.pvPower > 0 ? '#ffb800' : '#00f0ff');
          this.propStateText.textContent = state.pvPower > 0 ? '正向高效推进' : '夜间低功耗平飞';
          this.propStateText.setAttribute('fill', '#38bdf8');
          this.shaftPower.textContent = `${Math.abs(state.motorPower)} W (耗电)`;
          this.shaftPower.setAttribute('fill', '#f8fafc');

          this.regenPowerCable.setAttribute('opacity', '0');
          this.regenFlowVec.setAttribute('opacity', '0');
          this.elevatorRudder.setAttribute('stroke', '#38bdf8');
        }

        // 5. 光伏发光态动态同步
        if (state.pvPower > 30) {
          const wingAlpha = Math.min(1, state.pvPower / 400);
          this.solarWingL.setAttribute('stroke', '#ffdd00');
          this.solarWingR.setAttribute('stroke', '#ffdd00');
          this.solarWingL.setAttribute('opacity', wingAlpha);
          this.solarWingR.setAttribute('opacity', wingAlpha);
          this.pvFlowVec.setAttribute('opacity', wingAlpha);
        } else {
          this.solarWingL.setAttribute('opacity', '0.1');
          this.solarWingR.setAttribute('opacity', '0.1');
          this.pvFlowVec.setAttribute('opacity', '0');
        }
      }
    }

    // 页面加载完成后立即自动播放,确保无论首开还是 iframe 重开均自动自持运转
    document.addEventListener('DOMContentLoaded', () => {
      window.simInstance = new SimulationApp();
    });
  </script>
</body>
</html>
积分规则:每轮对话扣10分