分享图
动画工坊
引擎就绪
<!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分