独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高保真气流原理可视化 - 康达效应</title>
<style>
:root {
--bg-color: #070b14;
--panel-bg: rgba(13, 20, 36, 0.7);
--primary-flow: #00f0ff;
--primary-flow-glow: rgba(0, 240, 255, 0.6);
--secondary-flow: #4da6ff;
--ambient-flow: #e2f1ff;
--fail-flow: #ff5555;
--hardware-stroke: #3a4b66;
--hardware-fill: #121a2f;
--text-color: #a8b8d0;
--text-highlight: #ffffff;
/* Animation Variables dynamically controlled by JS */
--anim-speed: 0.8s;
--coanda-opacity: 1;
--fail-opacity: 0;
--entrain-opacity: 1;
--pressure-glow: 1;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'JetBrains Mono', 'Roboto Mono', 'SFMono-Regular', Consolas, monospace;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
width: 100vw;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
background-image:
radial-gradient(circle at 50% 50%, #111a30 0%, #070b14 80%),
linear-gradient(rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* HUD Overlay styling */
.hud-container {
position: absolute;
top: 20px;
left: 20px;
z-index: 10;
pointer-events: none;
max-width: 300px;
}
.hud-title {
font-size: 14px;
font-weight: bold;
color: var(--text-highlight);
text-transform: uppercase;
letter-spacing: 2px;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.hud-title::before {
content: '';
display: block;
width: 8px;
height: 8px;
background-color: var(--primary-flow);
border-radius: 50%;
box-shadow: 0 0 8px var(--primary-flow);
}
.hud-desc {
font-size: 11px;
line-height: 1.6;
color: var(--text-color);
background: var(--panel-bg);
padding: 10px 15px;
border-left: 2px solid var(--primary-flow);
backdrop-filter: blur(4px);
}
/* Control Panel */
.control-panel {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: var(--panel-bg);
border: 1px solid var(--hardware-stroke);
padding: 15px 25px;
border-radius: 8px;
z-index: 10;
display: flex;
flex-direction: column;
gap: 10px;
min-width: 300px;
backdrop-filter: blur(8px);
}
.control-header {
display: flex;
justify-content: space-between;
font-size: 12px;
color: var(--text-highlight);
}
.status-badge {
font-size: 10px;
padding: 2px 6px;
border-radius: 4px;
background: rgba(0, 240, 255, 0.2);
color: var(--primary-flow);
border: 1px solid rgba(0, 240, 255, 0.4);
}
.status-badge.warning {
background: rgba(255, 85, 85, 0.2);
color: var(--fail-flow);
border-color: rgba(255, 85, 85, 0.4);
}
/* Custom Slider */
input[type=range] {
-webkit-appearance: none;
width: 100%;
background: transparent;
}
input[type=range]:focus { outline: none; }
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: #1e293b;
border-radius: 2px;
}
input[type=range]::-webkit-slider-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--primary-flow);
cursor: pointer;
-webkit-appearance: none;
margin-top: -6px;
box-shadow: 0 0 10px var(--primary-flow);
transition: background 0.3s, box-shadow 0.3s;
}
input[type=range].warning-state::-webkit-slider-thumb {
background: var(--fail-flow);
box-shadow: 0 0 10px var(--fail-flow);
}
/* SVG Container */
.svg-container {
flex-grow: 1;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-height: 800px;
}
/* SVG Animations */
.flow-line {
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
animation: dash var(--anim-speed) linear infinite;
}
.flow-primary {
stroke: var(--primary-flow);
opacity: var(--coanda-opacity);
filter: drop-shadow(0 0 4px var(--primary-flow-glow));
}
.flow-secondary {
stroke: var(--secondary-flow);
opacity: var(--coanda-opacity);
}
.flow-ambient {
stroke: var(--ambient-flow);
opacity: var(--entrain-opacity);
animation: dash calc(var(--anim-speed) * 1.5) linear infinite;
}
.flow-fail {
stroke: var(--fail-flow);
opacity: var(--fail-opacity);
filter: drop-shadow(0 0 4px rgba(255, 85, 85, 0.5));
animation: dash calc(var(--anim-speed) * 0.8) linear infinite;
}
.pressure-zone {
opacity: calc(var(--pressure-glow) * 0.4);
animation: pulse 2s ease-in-out infinite alternate;
}
@keyframes dash {
to { stroke-dashoffset: -100; }
}
@keyframes pulse {
0% { transform: scale(0.95); opacity: calc(var(--pressure-glow) * 0.2); }
100% { transform: scale(1.05); opacity: calc(var(--pressure-glow) * 0.5); }
}
/* Hardware styling */
.hardware-body {
fill: url(#hardwareGrad);
stroke: var(--hardware-stroke);
stroke-width: 2;
}
.hardware-cutout {
fill: url(#cutoutGrad);
stroke: #475569;
stroke-width: 1;
}
.annotation-line {
stroke: #64748b;
stroke-width: 1;
stroke-dasharray: 2 2;
fill: none;
}
.annotation-text {
font-size: 12px;
fill: #cbd5e1;
dominant-baseline: middle;
}
.annotation-bg {
fill: rgba(7, 11, 20, 0.8);
}
.glow-point {
fill: var(--primary-flow);
animation: point-pulse 1.5s infinite alternate;
}
@keyframes point-pulse {
0% { r: 2; filter: drop-shadow(0 0 2px var(--primary-flow)); }
100% { r: 4; filter: drop-shadow(0 0 6px var(--primary-flow)); }
}
</style>
</head>
<body>
<!-- Absolute positioned HUD -->
<div class="hud-container">
<div class="hud-title">IFR 最终理想解可视化</div>
<div class="hud-desc">
破除摩擦矛盾:通过引入水滴形中心锥构建1.2mm环形窄缝。高速薄膜气流依托康达效应紧贴16°曲面流动,消除与内壁面的整体剪切摩擦,并利用尾部负压平顺卷吸静止空气,实现动能的高效传递与放大。
</div>
</div>
<!-- Interactive Control -->
<div class="control-panel">
<div class="control-header">
<span>电机风压输入 (静态压力)</span>
<span id="status-indicator" class="status-badge">附壁效应稳定</span>
</div>
<input type="range" id="pressure-slider" min="0" max="100" value="100">
<div style="display: flex; justify-content: space-between; font-size: 10px; color: #64748b;">
<span>失速临界点</span>
<span>100% 额定功率</span>
</div>
</div>
<!-- Main Visualization Area -->
<div class="svg-container">
<svg viewBox="0 0 1200 600" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- Hardware Gradients -->
<linearGradient id="hardwareGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="50%" stop-color="#0f172a" />
<stop offset="100%" stop-color="#1e293b" />
</linearGradient>
<linearGradient id="cutoutGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#020617" />
<stop offset="50%" stop-color="#0f172a" />
<stop offset="100%" stop-color="#020617" />
</linearGradient>
<!-- Pressure Zone Radial Gradient -->
<radialGradient id="lowPressureGrad">
<stop offset="0%" stop-color="#00f0ff" stop-opacity="0.8" />
<stop offset="40%" stop-color="#0066ff" stop-opacity="0.3" />
<stop offset="100%" stop-color="#000000" stop-opacity="0" />
</radialGradient>
<!-- Glow Filter -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Background Grid (subtle) -->
<g stroke="rgba(255,255,255,0.03)" stroke-width="1">
<line x1="400" y1="0" x2="400" y2="600" />
<line x1="600" y1="0" x2="600" y2="600" />
<line x1="800" y1="0" x2="800" y2="600" />
<line x1="0" y1="300" x2="1200" y2="300" stroke-dasharray="5 5" stroke="rgba(255,255,255,0.05)" />
</g>
<!-- Negative Pressure Zone (Visualizing Entrainment Force) -->
<ellipse cx="650" cy="300" rx="150" ry="120" fill="url(#lowPressureGrad)" class="pressure-zone" />
<!-- HARDWARE LAYER -->
<g id="hardware">
<!-- Outer Duct Top -->
<path d="M -50 150 L 400 150 C 450 150, 480 140, 500 140 L 1250 140 L 1250 0 L -50 0 Z" class="hardware-body" />
<!-- Outer Duct Bottom -->
<path d="M -50 450 L 400 450 C 450 450, 480 460, 500 460 L 1250 460 L 1250 600 L -50 600 Z" class="hardware-body" />
<!-- Central Teardrop/Airfoil Cone -->
<!-- The narrow gap is at x=400, y=152 & y=448 (leaves tiny gap against duct) -->
<path d="M 150 300
C 150 160, 350 152, 400 152
C 550 152, 700 280, 850 300
C 700 320, 550 448, 400 448
C 350 448, 150 440, 150 300 Z"
class="hardware-body" />
<!-- Internal Cutout/Details for tech aesthetic -->
<path d="M 200 300 C 200 180, 330 170, 380 170 L 380 430 C 330 430, 200 420, 200 300 Z" class="hardware-cutout" />
<line x1="380" y1="170" x2="380" y2="430" stroke="#3a4b66" stroke-width="2" />
</g>
<!-- AIRFLOW LAYER -->
<g id="airflow-field" filter="url(#glow)">
<!-- Ideal State: Coanda Effect Active (Top) -->
<!-- Primary High-Speed Flow (Cyan) squeezing through gap and hugging curve -->
<g class="flow-primary" stroke-width="2.5" stroke-dasharray="15 10">
<path d="M 0 180 Q 250 180 350 160 Q 380 155 400 155 C 550 155, 680 270, 850 285 L 1200 285" />
<path d="M 0 200 Q 250 200 350 163 Q 380 157 400 157 C 550 157, 680 275, 850 290 L 1200 290" stroke-width="1.5" stroke-dasharray="8 8" />
</g>
<!-- Ideal State: Coanda Effect Active (Bottom) -->
<g class="flow-primary" stroke-width="2.5" stroke-dasharray="15 10">
<path d="M 0 420 Q 250 420 350 440 Q 380 445 400 445 C 550 445, 680 330, 850 315 L 1200 315" />
<path d="M 0 400 Q 250 400 350 437 Q 380 443 400 443 C 550 443, 680 325, 850 310 L 1200 310" stroke-width="1.5" stroke-dasharray="8 8" />
</g>
<!-- Failure State: Stall / Flow Detachment (Visible only when pressure drops) -->
<!-- Flow shoots straight, doesn't hug curve -->
<g class="flow-fail" stroke-width="2" stroke-dasharray="10 15">
<path d="M 380 155 L 1200 155" />
<path d="M 380 158 L 1200 158" stroke-width="1" />
<path d="M 380 445 L 1200 445" />
<path d="M 380 442 L 1200 442" stroke-width="1" />
</g>
<!-- Entrained Ambient Air (Secondary Flow) -->
<g class="flow-ambient" stroke-width="1.5" stroke-dasharray="6 12">
<!-- Top entrainment -->
<path d="M 450 10 Q 550 100 650 240 L 1200 240" />
<path d="M 600 10 Q 650 120 750 260 L 1200 260" />
<!-- Bottom entrainment -->
<path d="M 450 590 Q 550 500 650 360 L 1200 360" />
<path d="M 600 590 Q 650 480 750 340 L 1200 340" />
<!-- Center straight through -->
<path d="M 900 300 L 1200 300" />
</g>
</g>
<!-- ANNOTATIONS & LABELS -->
<g id="annotations">
<!-- 1.2mm Gap Annotation -->
<circle cx="400" cy="153.5" r="3" class="glow-point" />
<path d="M 400 153.5 L 350 80 L 250 80" class="annotation-line" />
<rect x="150" y="70" width="95" height="20" rx="3" class="annotation-bg" />
<text x="155" y="81" class="annotation-text" fill="var(--primary-flow)">1.2mm 环形缝隙</text>
<!-- 16 Degree Curve Annotation -->
<circle cx="550" cy="190" r="3" class="glow-point" />
<path d="M 550 190 L 600 100 L 700 100" class="annotation-line" />
<rect x="705" y="90" width="105" height="20" rx="3" class="annotation-bg" />
<text x="710" y="101" class="annotation-text">16° 附壁曲面设计</text>
<!-- Negative Pressure Zone Annotation -->
<path d="M 650 300 L 750 450 L 850 450" class="annotation-line" />
<rect x="855" y="440" width="85" height="20" rx="3" class="annotation-bg" />
<text x="860" y="451" class="annotation-text" fill="var(--secondary-flow)">负压卷吸区</text>
<!-- Input Flow Label -->
<text x="20" y="290" class="annotation-text" style="font-size: 10px; opacity: 0.5;">高压气流输入</text>
<path d="M 20 300 L 100 300" stroke="#cbd5e1" stroke-width="1" stroke-opacity="0.3" marker-end="url(#arrow)" />
</g>
<!-- Marker Def -->
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="4" markerHeight="4" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#cbd5e1" fill-opacity="0.3" />
</marker>
</defs>
</svg>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const slider = document.getElementById('pressure-slider');
const root = document.documentElement;
const statusIndicator = document.getElementById('status-indicator');
function updateFluidDynamics() {
const pressure = parseInt(slider.value, 10);
// Calculate dynamics based on pressure percentage
// At 100%, flow is fast (speed 0.5s), coanda is 100%, failure is 0%
// At 0%, flow is slow (speed 2s), coanda is 0%, failure is 100%
const speed = 2 - (pressure / 100) * 1.5; // Maps 0-100 to 2s-0.5s
let coandaOpacity = 1;
let failOpacity = 0;
let entrainOpacity = 1;
let pressureGlow = 1;
// Threshold for stall / detachment
const STALL_THRESHOLD = 40;
if (pressure < STALL_THRESHOLD) {
// Stalled state
const ratio = pressure / STALL_THRESHOLD; // 0 to 1
coandaOpacity = ratio * 0.5; // Fades out
failOpacity = 1 - ratio; // Fades in
entrainOpacity = ratio * 0.3; // Entrainment dies quickly
pressureGlow = ratio * 0.2;
statusIndicator.textContent = '警告: 风压不足导致气流脱离 (失速)';
statusIndicator.className = 'status-badge warning';
slider.classList.add('warning-state');
} else {
// Healthy attached state
const ratio = (pressure - STALL_THRESHOLD) / (100 - STALL_THRESHOLD);
coandaOpacity = 0.5 + (ratio * 0.5);
failOpacity = 0;
entrainOpacity = 0.3 + (ratio * 0.7);
pressureGlow = 0.2 + (ratio * 0.8);
statusIndicator.textContent = '附壁效应稳定 (平顺流动)';
statusIndicator.className = 'status-badge';
slider.classList.remove('warning-state');
}
// Apply to CSS variables
root.style.setProperty('--anim-speed', `${speed}s`);
root.style.setProperty('--coanda-opacity', coandaOpacity);
root.style.setProperty('--fail-opacity', failOpacity);
root.style.setProperty('--entrain-opacity', entrainOpacity);
root.style.setProperty('--pressure-glow', pressureGlow);
}
// Listen to slider changes
slider.addEventListener('input', updateFluidDynamics);
// Initialize
updateFluidDynamics();
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
