独立渲染引擎就绪引擎就绪
<!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分
等待动画代码生成...
