独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>串列双翼太阳能 VTOL 原理可视化</title>
<style>
:root {
--bg-color: #070c14;
--panel-bg: rgba(13, 23, 38, 0.72);
--panel-border: rgba(56, 189, 248, 0.18);
--accent-solar: #f59e0b;
--accent-solar-glow: rgba(245, 158, 11, 0.4);
--accent-cyan: #38bdf8;
--accent-thrust: #60a5fa;
--accent-battery: #10b981;
--accent-warn: #f43f5e;
--text-main: #e2e8f0;
--text-muted: #94a3b8;
--font-mono: ui-monospace, SFMono-Regular, "JetBrains Mono", Menlo, 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-color);
color: var(--text-main);
font-family: var(--font-sans);
width: 100vw;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
position: relative;
}
/* 科技感背景网格 */
.bg-grid {
position: absolute;
inset: 0;
background-image:
radial-gradient(ellipse at 50% 35%, rgba(14, 165, 233, 0.12) 0%, transparent 60%),
linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
background-size: 100% 100%, 48px 48px, 48px 48px;
pointer-events: none;
z-index: 1;
}
/* 主画布区域:SVG居中满幅,占据绝对视觉主角 */
.stage-container {
position: relative;
flex: 1;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 2;
}
svg#main-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 860px;
filter: drop-shadow(0 0 24px rgba(0, 0, 0, 0.6));
}
/* 轻量边角 HUD 说明(字号小、避开中央,绝不遮挡核心动画) */
.hud-header {
position: absolute;
top: 16px;
left: 20px;
z-index: 10;
display: flex;
flex-direction: column;
gap: 4px;
pointer-events: none;
}
.hud-title {
font-size: 15px;
font-weight: 700;
letter-spacing: 0.06em;
color: #f8fafc;
display: flex;
align-items: center;
gap: 8px;
}
.hud-badge {
font-size: 10px;
padding: 2px 6px;
border-radius: 4px;
background: rgba(16, 185, 129, 0.18);
color: #34d399;
border: 1px solid rgba(52, 211, 153, 0.35);
font-family: var(--font-mono);
}
.hud-sub {
font-size: 11px;
color: var(--text-muted);
letter-spacing: 0.02em;
}
/* 右上角实时能量收支仪表盘 */
.hud-metrics {
position: absolute;
top: 16px;
right: 20px;
z-index: 10;
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
padding: 10px 14px;
border-radius: 8px;
font-family: var(--font-mono);
font-size: 11px;
display: flex;
flex-direction: column;
gap: 6px;
min-width: 210px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
}
.metric-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.metric-name {
color: var(--text-muted);
display: flex;
align-items: center;
gap: 6px;
}
.metric-val {
font-weight: 700;
color: #f1f5f9;
}
.dot-solar { width: 7px; height: 7px; border-radius: 50%; background: var(--accent-solar); box-shadow: 0 0 6px var(--accent-solar); }
.dot-thrust { width: 7px; height: 7px; border-radius: 50%; background: var(--accent-thrust); box-shadow: 0 0 6px var(--accent-thrust); }
.dot-net { width: 7px; height: 7px; border-radius: 50%; background: var(--accent-battery); box-shadow: 0 0 6px var(--accent-battery); }
/* 状态阶段指示条 */
.mode-bar {
margin-top: 4px;
padding-top: 6px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
display: flex;
justify-content: space-between;
align-items: center;
}
.mode-tag {
font-weight: 700;
font-size: 11px;
padding: 1px 6px;
border-radius: 3px;
}
.mode-cruise {
color: #38bdf8;
background: rgba(56, 189, 248, 0.15);
border: 1px solid rgba(56, 189, 248, 0.3);
}
.mode-vtol {
color: #f43f5e;
background: rgba(244, 63, 94, 0.15);
border: 1px solid rgba(244, 63, 94, 0.3);
}
/* 底部控制托盘(紧凑、半透明悬浮) */
.bottom-bar {
position: absolute;
bottom: 14px;
left: 50%;
transform: translateX(-50%);
z-index: 10;
display: flex;
align-items: center;
gap: 16px;
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
padding: 8px 18px;
border-radius: 30px;
font-size: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.btn-play {
background: #0284c7;
border: none;
color: #ffffff;
width: 28px;
height: 28px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
transition: all 0.2s ease;
outline: none;
}
.btn-play:hover {
background: #0ea5e9;
box-shadow: 0 0 10px rgba(14, 165, 233, 0.6);
transform: scale(1.05);
}
.stage-tabs {
display: flex;
gap: 6px;
}
.stage-chip {
padding: 4px 10px;
border-radius: 14px;
cursor: pointer;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: var(--text-muted);
font-size: 11px;
transition: all 0.2s;
}
.stage-chip:hover {
background: rgba(255, 255, 255, 0.12);
color: #fff;
}
.stage-chip.active {
background: rgba(56, 189, 248, 0.2);
border-color: #38bdf8;
color: #38bdf8;
font-weight: 600;
box-shadow: 0 0 8px rgba(56, 189, 248, 0.25);
}
.scrubber {
width: 130px;
accent-color: #38bdf8;
cursor: pointer;
}
.legend-chip {
display: flex;
align-items: center;
gap: 5px;
font-size: 11px;
color: var(--text-muted);
}
/* 动画关键帧与微动 */
@keyframes pulseGlow {
0%, 100% { opacity: 0.35; filter: drop-shadow(0 0 6px var(--accent-solar-glow)); }
50% { opacity: 0.85; filter: drop-shadow(0 0 14px var(--accent-solar)); }
}
@keyframes propSpin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes flowDash {
to { stroke-dashoffset: -40; }
}
@keyframes flowDashReverse {
to { stroke-dashoffset: 40; }
}
.solar-pulse {
animation: pulseGlow 2.4s ease-in-out infinite;
}
.flow-line {
stroke-dasharray: 6, 4;
animation: flowDash 0.8s linear infinite;
}
.flow-reverse {
stroke-dasharray: 6, 4;
animation: flowDashReverse 0.8s linear infinite;
}
</style>
</head>
<body>
<!-- 背景网格修饰 -->
<div class="bg-grid"></div>
<!-- 左上轻量概览说明(不遮挡主飞行器) -->
<header class="hud-header">
<div class="hud-title">
<span>TANDEM-WING SOLAR VTOL</span>
<span class="hud-badge">IFR 最终理想解</span>
</div>
<div class="hud-sub">串列翼气动解耦 · 旋翼悬停与翼面巡航时序分离 · 净能正收益闭环</div>
</header>
<!-- 右上角能量状态仪表板 -->
<div class="hud-metrics">
<div class="metric-row">
<span class="metric-name"><span class="dot-solar"></span>薄膜光伏收集</span>
<span class="metric-val" id="val-solar">126.5 W</span>
</div>
<div class="metric-row">
<span class="metric-name"><span class="dot-thrust"></span>整机动力+航电</span>
<span class="metric-val" id="val-thrust">57.0 W</span>
</div>
<div class="metric-row">
<span class="metric-name"><span class="dot-net"></span>能量自持净盈余</span>
<span class="metric-val" style="color: #34d399;" id="val-net">+69.5 W</span>
</div>
<div class="mode-bar">
<span style="color: var(--text-muted);">气动模态 / 升阻比</span>
<span class="mode-tag mode-cruise" id="val-aero">巡航 L/D = 18</span>
</div>
</div>
<!-- SVG 原理核心主画布 -->
<main class="stage-container">
<svg id="main-svg" viewBox="0 0 1000 620" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 渐变定义 -->
<linearGradient id="cigsGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="45%" stop-color="#1e3a5f" />
<stop offset="70%" stop-color="#2563eb" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="sunBeam" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#f59e0b" stop-opacity="0.35" />
<stop offset="100%" stop-color="#fbbf24" stop-opacity="0" />
</linearGradient>
<radialGradient id="sunOrigin" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#fef08a" />
<stop offset="40%" stop-color="#f59e0b" stop-opacity="0.8" />
<stop offset="100%" stop-color="#b45309" stop-opacity="0" />
</radialGradient>
<linearGradient id="fuselageGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#334155" />
<stop offset="35%" stop-color="#0f172a" />
<stop offset="65%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#090d16" />
</linearGradient>
<filter id="glow" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 太阳能电池网格纹理 -->
<pattern id="solarGrid" width="12" height="12" patternUnits="userSpaceOnUse">
<path d="M 12 0 L 0 0 0 12" fill="none" stroke="rgba(56, 189, 248, 0.22)" stroke-width="0.75" />
</pattern>
<!-- 气流微粒标记 -->
<marker id="arrowHead" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="4" markerHeight="4" orient="auto">
<polygon points="0 1, 7 4, 0 7" fill="#38bdf8" />
</marker>
</defs>
<!-- 1. 光照与能量场层 -->
<g id="sun-layer">
<!-- 模拟高空太阳光伏射场 -->
<circle cx="500" cy="-60" r="140" fill="url(#sunOrigin)" filter="url(#glow)" />
<g id="photon-beams" opacity="0.6">
<polygon points="400,0 260,260 290,260" fill="url(#sunBeam)" />
<polygon points="460,0 380,260 410,260" fill="url(#sunBeam)" />
<polygon points="540,0 590,260 620,260" fill="url(#sunBeam)" />
<polygon points="600,0 710,260 740,260" fill="url(#sunBeam)" />
<polygon points="320,0 120,380 150,380" fill="url(#sunBeam)" />
<polygon points="680,0 850,380 880,380" fill="url(#sunBeam)" />
</g>
<!-- 漂浮的光子粒子 -->
<g id="photons-particles"></g>
</g>
<!-- 2. 空气动力学流线层(巡航高升阻比气流) -->
<g id="aero-streamlines" opacity="0.35">
<path d="M 60,240 C 220,240 380,225 500,225 C 640,225 780,240 940,240" fill="none" stroke="#38bdf8" stroke-width="1.2" stroke-dasharray="8 12" class="flow-line" />
<path d="M 40,290 C 240,290 380,270 500,270 C 640,270 760,290 960,290" fill="none" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="10 14" class="flow-line" />
<path d="M 70,350 C 260,350 400,340 500,340 C 620,340 740,350 930,350" fill="none" stroke="#38bdf8" stroke-width="1.2" stroke-dasharray="8 10" class="flow-line" />
</g>
<!-- 3. 飞行器主体组(俯仰角三维轴测透视俯视) -->
<g id="aircraft-group" transform="translate(0, 0)">
<!-- ================= 后翼(上翼后掠布局,抬高布置) ================= -->
<g id="aft-wing">
<!-- 机翼底衬 -->
<polygon points="210,195 500,220 790,195 770,250 500,265 230,250" fill="#0b1329" stroke="rgba(56, 189, 248, 0.4)" stroke-width="1.5" />
<!-- CIGS 柔性薄膜光伏上表面铺覆 -->
<polygon id="aft-cigs" points="214,198 500,222 786,198 766,247 500,262 234,247" fill="url(#cigsGradient)" />
<polygon points="214,198 500,222 786,198 766,247 500,262 234,247" fill="url(#solarGrid)" opacity="0.65" />
<!-- 翼展尺寸与光伏微光 -->
<line x1="205" y1="195" x2="205" y2="250" stroke="#f59e0b" stroke-width="2" opacity="0.7" />
<line x1="795" y1="195" x2="795" y2="250" stroke="#f59e0b" stroke-width="2" opacity="0.7" />
<!-- 后翼两端垂直翼梢小翼 -->
<polygon points="208,188 214,196 230,254 224,258" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<polygon points="792,188 786,196 770,254 776,258" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
</g>
<!-- ================= 尾撑杆与机体连接构架 ================= -->
<g id="booms" stroke="#475569" stroke-width="3">
<line x1="330" y1="230" x2="330" y2="400" />
<line x1="670" y1="230" x2="670" y2="400" />
</g>
<!-- ================= 前翼(下翼前掠布局,翼展更宽,降低下洗干扰) ================= -->
<g id="fore-wing">
<!-- 机翼碳纤维基体 -->
<polygon points="120,380 500,345 880,380 860,430 500,388 140,430" fill="#0f172a" stroke="rgba(56, 189, 248, 0.5)" stroke-width="1.5" />
<!-- CIGS 柔性薄膜上表面共形贴合 -->
<polygon id="fore-cigs" points="125,382 500,348 875,382 855,426 500,385 145,426" fill="url(#cigsGradient)" />
<polygon points="125,382 500,348 875,382 855,426 500,385 145,426" fill="url(#solarGrid)" opacity="0.65" />
<!-- 翼尖垂尾 -->
<polygon points="116,370 125,380 144,435 135,440" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<polygon points="884,370 875,380 856,435 865,440" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
</g>
<!-- ================= 中央流线机身与航电设备舱 ================= -->
<g id="fuselage">
<!-- 流线型修长机身 -->
<path d="M 490,175 C 490,165 510,165 510,175 L 514,440 C 514,458 507,475 500,478 C 493,475 486,458 486,440 Z" fill="url(#fuselageGrad)" stroke="#38bdf8" stroke-width="1.2" />
<!-- 机身内部架构透视:MPPT与中央电池缓冲舱 -->
<rect x="492" y="325" width="16" height="32" rx="3" fill="#065f46" stroke="#10b981" stroke-width="1.2" />
<text x="500" y="344" fill="#a7f3d0" font-size="7" font-weight="bold" font-family="monospace" text-anchor="middle">BAT</text>
<rect x="492" y="275" width="16" height="22" rx="3" fill="#854d0e" stroke="#f59e0b" stroke-width="1.2" />
<text x="500" y="289" fill="#fde68a" font-size="7" font-weight="bold" font-family="monospace" text-anchor="middle">MPPT</text>
</g>
<!-- ================= 尾推电机与螺旋桨(巡航主推进器) ================= -->
<g id="tail-pusher" transform="translate(500, 482)">
<!-- 电机短舱圆环 -->
<circle cx="0" cy="0" r="7" fill="#1e293b" stroke="#60a5fa" stroke-width="1.5" />
<!-- 高速尾推桨叶动画组 -->
<g id="pusher-blades">
<line x1="-30" y1="0" x2="30" y2="0" stroke="#93c5fd" stroke-width="2.5" stroke-linecap="round" opacity="0.85" />
<line x1="0" y1="-30" x2="0" y2="30" stroke="#93c5fd" stroke-width="2.5" stroke-linecap="round" opacity="0.85" />
<circle cx="0" cy="0" r="32" fill="none" stroke="rgba(147, 197, 253, 0.25)" stroke-dasharray="4 4" />
</g>
<!-- 尾部推进尾迹射流 -->
<g id="pusher-jet" opacity="0.8">
<polygon points="-12,12 12,12 0,55" fill="url(#sunBeam)" opacity="0.4" />
<line x1="0" y1="10" x2="0" y2="60" stroke="#38bdf8" stroke-width="1.8" stroke-dasharray="4 6" class="flow-line" />
<line x1="-8" y1="10" x2="-16" y2="52" stroke="#60a5fa" stroke-width="1.2" stroke-dasharray="3 5" class="flow-line" />
<line x1="8" y1="10" x2="16" y2="52" stroke="#60a5fa" stroke-width="1.2" stroke-dasharray="3 5" class="flow-line" />
</g>
</g>
<!-- ================= 四个倾转旋翼短舱 (VTOL Pods) ================= -->
<!-- 左后旋翼短舱 (Rotor 1) -->
<g id="pod-rl" transform="translate(330, 230)">
<rect x="-6" y="-12" width="12" height="24" rx="3" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<g id="rotor-rl-spinner" class="rotor-spinner">
<!-- 桨叶(巡航时顺桨折叠成横向,垂直时旋转) -->
<ellipse id="disk-rl" cx="0" cy="0" rx="34" ry="12" fill="rgba(56, 189, 248, 0.2)" stroke="#38bdf8" stroke-dasharray="4 2" />
<line id="feather-rl" x1="-34" y1="0" x2="34" y2="0" stroke="#bae6fd" stroke-width="2" />
</g>
<!-- 悬停喷流向下箭头(VTOL阶段高亮显示) -->
<g id="thrust-rl" opacity="0">
<line x1="0" y1="12" x2="0" y2="40" stroke="#f43f5e" stroke-width="2.5" stroke-dasharray="4 4" class="flow-line" />
</g>
</g>
<!-- 右后旋翼短舱 (Rotor 2) -->
<g id="pod-rr" transform="translate(670, 230)">
<rect x="-6" y="-12" width="12" height="24" rx="3" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<g id="rotor-rr-spinner" class="rotor-spinner">
<ellipse id="disk-rr" cx="0" cy="0" rx="34" ry="12" fill="rgba(56, 189, 248, 0.2)" stroke="#38bdf8" stroke-dasharray="4 2" />
<line id="feather-rr" x1="-34" y1="0" x2="34" y2="0" stroke="#bae6fd" stroke-width="2" />
</g>
<g id="thrust-rr" opacity="0">
<line x1="0" y1="12" x2="0" y2="40" stroke="#f43f5e" stroke-width="2.5" stroke-dasharray="4 4" class="flow-line" />
</g>
</g>
<!-- 左前旋翼短舱 (Rotor 3) -->
<g id="pod-fl" transform="translate(330, 400)">
<rect x="-6" y="-12" width="12" height="24" rx="3" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<g id="rotor-fl-spinner" class="rotor-spinner">
<ellipse id="disk-fl" cx="0" cy="0" rx="34" ry="12" fill="rgba(56, 189, 248, 0.2)" stroke="#38bdf8" stroke-dasharray="4 2" />
<line id="feather-fl" x1="-34" y1="0" x2="34" y2="0" stroke="#bae6fd" stroke-width="2" />
</g>
<g id="thrust-fl" opacity="0">
<line x1="0" y1="12" x2="0" y2="40" stroke="#f43f5e" stroke-width="2.5" stroke-dasharray="4 4" class="flow-line" />
</g>
</g>
<!-- 右前旋翼短舱 (Rotor 4) -->
<g id="pod-fr" transform="translate(670, 400)">
<rect x="-6" y="-12" width="12" height="24" rx="3" fill="#1e293b" stroke="#38bdf8" stroke-width="1" />
<g id="rotor-fr-spinner" class="rotor-spinner">
<ellipse id="disk-fr" cx="0" cy="0" rx="34" ry="12" fill="rgba(56, 189, 248, 0.2)" stroke="#38bdf8" stroke-dasharray="4 2" />
<line id="feather-fr" x1="-34" y1="0" x2="34" y2="0" stroke="#bae6fd" stroke-width="2" />
</g>
<g id="thrust-fr" opacity="0">
<line x1="0" y1="12" x2="0" y2="40" stroke="#f43f5e" stroke-width="2.5" stroke-dasharray="4 4" class="flow-line" />
</g>
</g>
<!-- ================= 4. 能量流拓扑总线(动态高亮流动) ================= -->
<g id="power-bus-layer">
<!-- 光伏收集流 -> MPPT -->
<path id="wire-solar-aft" d="M 360,225 L 492,282 M 640,225 L 508,282" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" class="flow-line" />
<path id="wire-solar-fore" d="M 280,395 L 492,290 M 720,395 L 508,290" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" class="flow-line" />
<!-- MPPT -> 尾推主母线 (巡航主供电) -->
<path id="wire-mppt-tail" d="M 500,297 L 500,475" fill="none" stroke="#60a5fa" stroke-width="3" stroke-linecap="round" class="flow-line" />
<!-- MPPT <-> 电池充电/放电总线 -->
<path id="wire-mppt-bat" d="M 500,297 L 500,325" fill="none" stroke="#10b981" stroke-width="3" stroke-linecap="round" class="flow-line" />
<!-- 电池 -> 4个旋翼短舱供电线路(VTOL爬升放电时激活) -->
<g id="wires-vtol-power" opacity="0.1">
<path d="M 492,340 L 330,230" fill="none" stroke="#f43f5e" stroke-width="2" class="flow-line" />
<path d="M 508,340 L 670,230" fill="none" stroke="#f43f5e" stroke-width="2" class="flow-line" />
<path d="M 492,345 L 330,400" fill="none" stroke="#f43f5e" stroke-width="2" class="flow-line" />
<path d="M 508,345 L 670,400" fill="none" stroke="#f43f5e" stroke-width="2" class="flow-line" />
</g>
</g>
</g>
<!-- 4. 关键解耦机理视觉标注(极简小字、指示线,不遮挡核心飞行器) -->
<g id="annotation-group" font-size="10" font-family="monospace">
<!-- 后翼上表面CIGS薄膜标注 -->
<g transform="translate(195, 170)">
<text x="0" y="0" fill="#f59e0b" font-weight="bold">后翼 CIGS 薄膜光伏 (上后掠)</text>
<line x1="120" y1="3" x2="160" y2="35" stroke="#f59e0b" stroke-width="0.8" opacity="0.6" />
</g>
<!-- 前翼下掠布局与低干扰标注 -->
<g transform="translate(70, 465)">
<text x="0" y="0" fill="#38bdf8" font-weight="bold">前翼下反前掠 (降低下洗干扰)</text>
<text x="0" y="14" fill="#94a3b8" font-size="9">翼展 3.2m · 巡航升阻比 18</text>
<line x1="160" y1="-8" x2="220" y2="-45" stroke="#38bdf8" stroke-width="0.8" opacity="0.6" />
</g>
<!-- 顺桨短舱机制标注 -->
<g id="label-feather" transform="translate(730, 290)">
<rect x="-6" y="-12" width="165" height="42" rx="4" fill="rgba(15,23,42,0.85)" stroke="rgba(56,189,248,0.3)" />
<text x="0" y="3" fill="#e2e8f0" font-weight="bold">旋翼停转顺桨 (Feathered)</text>
<text x="0" y="18" fill="#38bdf8" font-size="9">零风阻锁定 · 消除悬停负收益</text>
<line x1="-6" y1="8" x2="-55" y2="-50" stroke="#38bdf8" stroke-width="0.8" opacity="0.6" />
</g>
<!-- 尾推高能效标注 -->
<g transform="translate(560, 520)">
<text x="0" y="0" fill="#60a5fa" font-weight="bold">尾推电机 (42W 巡航推进)</text>
<text x="0" y="14" fill="#34d399" font-size="9">光伏净盈余 +69.5W 直充蓄电池</text>
<line x1="-10" y1="-4" x2="-45" y2="-30" stroke="#60a5fa" stroke-width="0.8" opacity="0.6" />
</g>
</g>
</svg>
</main>
<!-- 底部微型浮动控制交互栏 -->
<footer class="bottom-bar">
<button class="btn-play" id="btn-play" title="播放/暂停">❚❚</button>
<div class="stage-tabs">
<div class="stage-chip" data-phase="0">1.垂直起飞 (VTOL)</div>
<div class="stage-chip" data-phase="1">2.倾转过渡</div>
<div class="stage-chip active" data-phase="2">3.太阳能自持巡航 (IFR)</div>
<div class="stage-chip" data-phase="3">4.垂直着陆</div>
</div>
<input type="range" id="time-scrubber" class="scrubber" min="0" max="1000" value="650" />
<div class="legend-chip">
<span style="display:inline-block;width:12px;height:2px;background:#f59e0b;"></span>
<span>光伏发电</span>
</div>
<div class="legend-chip">
<span style="display:inline-block;width:12px;height:2px;background:#10b981;"></span>
<span>储能回充</span>
</div>
</footer>
<script>
// ==========================================
// 动画状态与物理参数模型
// ==========================================
const DURATION = 16000; // 完整工作时序周期 16 秒
let isPlaying = true;
let startTime = performance.now();
let pausedTime = 0;
let manualProgress = null;
// DOM 元素引用
const playBtn = document.getElementById('btn-play');
const scrubber = document.getElementById('time-scrubber');
const stageChips = document.querySelectorAll('.stage-chip');
const photonsContainer = document.getElementById('photons-particles');
// HUD 数值指示
const valSolar = document.getElementById('val-solar');
const valThrust = document.getElementById('val-thrust');
const valNet = document.getElementById('val-net');
const valAero = document.getElementById('val-aero');
// SVG 动态部件
const pusherBlades = document.getElementById('pusher-blades');
const pusherJet = document.getElementById('tail-pusher').querySelector('#pusher-jet');
const aeroStreamlines = document.getElementById('aero-streamlines');
const wiresVtolPower = document.getElementById('wires-vtol-power');
const wireMpptBat = document.getElementById('wire-mppt-bat');
const labelFeather = document.getElementById('label-feather');
const photonBeams = document.getElementById('photon-beams');
// 4个短舱元素
const pods = [
{ disk: document.getElementById('disk-rl'), feather: document.getElementById('feather-rl'), thrust: document.getElementById('thrust-rl') },
{ disk: document.getElementById('disk-rr'), feather: document.getElementById('feather-rr'), thrust: document.getElementById('thrust-rr') },
{ disk: document.getElementById('disk-fl'), feather: document.getElementById('feather-fl'), thrust: document.getElementById('thrust-fl') },
{ disk: document.getElementById('disk-fr'), feather: document.getElementById('feather-fr'), thrust: document.getElementById('thrust-fr') }
];
// 初始化随机漂落的太阳能光子雨
const PHOTON_COUNT = 24;
const photons = [];
for (let i = 0; i < PHOTON_COUNT; i++) {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('r', (Math.random() * 2 + 1.2).toFixed(1));
circle.setAttribute('fill', '#fde047');
circle.setAttribute('opacity', (Math.random() * 0.7 + 0.3).toFixed(2));
circle.setAttribute('filter', 'url(#glow)');
photonsContainer.appendChild(circle);
photons.push({
el: circle,
x: Math.random() * 800 + 100,
y: Math.random() * 300,
speed: Math.random() * 1.5 + 1.2
});
}
// 阶段划分:
// 0.00 ~ 0.22 : 阶段0 - 垂直起飞 (VTOL),旋翼大功率,电池大放电
// 0.22 ~ 0.38 : 阶段1 - 倾转过渡 (Transition),旋翼倾转并开始顺桨,尾推介入
// 0.38 ~ 0.85 : 阶段2 - 太阳能自持巡航 (IFR 核心理想解),旋翼顺桨锁死,升阻比18,光能直供且余电反充
// 0.85 ~ 1.00 : 阶段3 - 垂直降落 (Landing),旋翼解顺并重新启动
function getPhaseIndex(t) {
if (t < 0.22) return 0;
if (t < 0.38) return 1;
if (t < 0.85) return 2;
return 3;
}
// 核心物理量与动效插值
function renderFrame(now) {
let elapsed;
if (manualProgress !== null) {
elapsed = manualProgress * DURATION;
} else {
elapsed = (now - startTime) % DURATION;
scrubber.value = ((elapsed / DURATION) * 1000).toFixed(0);
}
const p = elapsed / DURATION;
const phase = getPhaseIndex(p);
// 更新下方阶段高亮按钮
stageChips.forEach((chip, idx) => {
chip.classList.toggle('active', idx === phase);
});
// 1. 太阳光子粒子下落更新
photons.forEach(pt => {
pt.y += pt.speed;
if (pt.y > 450) {
pt.y = Math.random() * 60;
pt.x = Math.random() * 800 + 100;
}
pt.el.setAttribute('cx', pt.x);
pt.el.setAttribute('cy', pt.y);
});
// 2. 尾推螺旋桨高速转动
const pusherAngle = (now * 1.4) % 360;
pusherBlades.setAttribute('transform', `rotate(${pusherAngle})`);
// 3. 模态插值运算与组件呈现
let solarPower = 126.5; // 恒定晴朗光照
let thrustPower = 0;
let netPower = 0;
let rotorTilt = 0; // 0: 垂直旋翼盘展开, 1: 顺桨横向
if (phase === 0) {
// [阶段0: 垂直起飞] 旋翼全功率,电池净消耗 -380W
thrustPower = 395;
netPower = solarPower - thrustPower; // -268.5W
rotorTilt = 0;
valSolar.textContent = `${solarPower.toFixed(1)} W`;
valThrust.textContent = `${thrustPower.toFixed(0)} W (旋翼为主)`;
valNet.textContent = `${netPower.toFixed(1)} W (电池深度放电)`;
valNet.style.color = '#f43f5e';
valAero.className = 'mode-tag mode-vtol';
valAero.textContent = '悬停模态 (能收支为负)';
wiresVtolPower.setAttribute('opacity', '0.9');
wireMpptBat.classList.add('flow-reverse'); // 电池放电
aeroStreamlines.setAttribute('opacity', '0.08');
pusherJet.setAttribute('opacity', '0.2');
labelFeather.setAttribute('opacity', '0.25');
// 旋翼桨盘高速旋转动效
pods.forEach(pod => {
pod.thrust.setAttribute('opacity', '0.9');
pod.disk.setAttribute('opacity', '0.65');
pod.feather.setAttribute('opacity', '0.2');
const spinScale = Math.sin(now * 0.05);
pod.disk.setAttribute('rx', 34 + spinScale * 2);
});
} else if (phase === 1) {
// [阶段1: 模态倾转] 短舱倾转、旋翼逐渐顺桨、尾推功率跃升
const transRatio = (p - 0.22) / (0.38 - 0.22);
thrustPower = 395 * (1 - transRatio) + 57 * transRatio;
netPower = solarPower - thrustPower;
rotorTilt = transRatio;
valSolar.textContent = `${solarPower.toFixed(1)} W`;
valThrust.textContent = `${thrustPower.toFixed(0)} W (倾转过渡)`;
valNet.textContent = `${netPower > 0 ? '+' : ''}${netPower.toFixed(1)} W`;
valNet.style.color = netPower > 0 ? '#34d399' : '#f59e0b';
valAero.className = 'mode-tag mode-cruise';
valAero.textContent = '倾转过渡 (升力面接管)';
wiresVtolPower.setAttribute('opacity', (0.9 * (1 - transRatio)).toFixed(2));
aeroStreamlines.setAttribute('opacity', (0.1 + 0.35 * transRatio).toFixed(2));
pusherJet.setAttribute('opacity', (0.2 + 0.7 * transRatio).toFixed(2));
labelFeather.setAttribute('opacity', (transRatio).toFixed(2));
pods.forEach(pod => {
pod.thrust.setAttribute('opacity', ((1 - transRatio) * 0.8).toFixed(2));
pod.disk.setAttribute('opacity', ((1 - transRatio) * 0.65).toFixed(2));
pod.feather.setAttribute('opacity', transRatio.toFixed(2));
pod.disk.setAttribute('rx', 34 * (1 - transRatio));
});
} else if (phase === 2) {
// [阶段2: 最终理想解巡航态 (IFR)] 太阳能自持!高升阻比 L/D=18
thrustPower = 57.0; // 尾推42W + 航电15W
netPower = solarPower - thrustPower; // +69.5W
valSolar.textContent = `${solarPower.toFixed(1)} W`;
valThrust.textContent = `57.0 W (尾推42W+航电15W)`;
valNet.textContent = `+${netPower.toFixed(1)} W (自持反充蓄电池)`;
valNet.style.color = '#34d399';
valAero.className = 'mode-tag mode-cruise';
valAero.textContent = '巡航 L/D = 18 (光伏自持)';
wiresVtolPower.setAttribute('opacity', '0.04');
wireMpptBat.classList.remove('flow-reverse'); // 电池回充
aeroStreamlines.setAttribute('opacity', '0.5');
pusherJet.setAttribute('opacity', '1.0');
labelFeather.setAttribute('opacity', '1.0');
// 4个短舱完全顺桨(零转速、零阻力顺流锁定)
pods.forEach(pod => {
pod.thrust.setAttribute('opacity', '0');
pod.disk.setAttribute('opacity', '0');
pod.feather.setAttribute('opacity', '1.0');
});
} else {
// [阶段3: 降落过渡]
const landRatio = (p - 0.85) / (1 - 0.85);
thrustPower = 57 * (1 - landRatio) + 380 * landRatio;
netPower = solarPower - thrustPower;
valSolar.textContent = `${solarPower.toFixed(1)} W`;
valThrust.textContent = `${thrustPower.toFixed(0)} W (旋翼复位)`;
valNet.textContent = `${netPower.toFixed(1)} W`;
valNet.style.color = '#f43f5e';
valAero.className = 'mode-tag mode-vtol';
valAero.textContent = '垂直降落 (旋翼重启)';
wiresVtolPower.setAttribute('opacity', (0.8 * landRatio).toFixed(2));
aeroStreamlines.setAttribute('opacity', (0.4 * (1 - landRatio)).toFixed(2));
pusherJet.setAttribute('opacity', (0.8 * (1 - landRatio)).toFixed(2));
pods.forEach(pod => {
pod.thrust.setAttribute('opacity', (landRatio * 0.7).toFixed(2));
pod.disk.setAttribute('opacity', (landRatio * 0.5).toFixed(2));
pod.feather.setAttribute('opacity', (1 - landRatio).toFixed(2));
pod.disk.setAttribute('rx', 34 * landRatio);
});
}
if (isPlaying) {
requestAnimationFrame(renderFrame);
}
}
// 交互响应:播放/暂停
playBtn.addEventListener('click', () => {
isPlaying = !isPlaying;
playBtn.textContent = isPlaying ? '❚❚' : '▶';
if (isPlaying) {
startTime = performance.now() - pausedTime;
requestAnimationFrame(renderFrame);
} else {
pausedTime = (performance.now() - startTime) % DURATION;
}
});
// 交互响应:时间轴拖动
scrubber.addEventListener('input', (e) => {
manualProgress = parseFloat(e.target.value) / 1000;
if (!isPlaying) {
renderFrame(performance.now());
}
});
scrubber.addEventListener('change', () => {
if (isPlaying) {
startTime = performance.now() - manualProgress * DURATION;
manualProgress = null;
}
});
// 交互响应:阶段芯片快速切换
const phaseMarkers = [0.05, 0.28, 0.55, 0.92];
stageChips.forEach(chip => {
chip.addEventListener('click', () => {
const ph = parseInt(chip.getAttribute('data-phase'));
const targetP = phaseMarkers[ph];
scrubber.value = targetP * 1000;
startTime = performance.now() - targetP * DURATION;
manualProgress = isPlaying ? null : targetP;
if (!isPlaying) {
renderFrame(performance.now());
}
});
});
// 页面加载完成后自动连续播放,重开即播
window.addEventListener('DOMContentLoaded', () => {
startTime = performance.now();
isPlaying = true;
requestAnimationFrame(renderFrame);
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
