分享图
动画工坊
引擎就绪
<!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-base: #050505;
            --bg-grid: #111111;
            --neon-cyan: #00f0ff;
            --neon-cyan-dim: rgba(0, 240, 255, 0.3);
            --neon-amber: #ffb000;
            --neon-amber-dim: rgba(255, 176, 0, 0.3);
            --steel: #475569;
            --steel-dark: #1e293b;
            --text-main: #f8fafc;
            --text-muted: #94a3b8;
            
            /* 动态可调变量,通过JS控制或默认起效 */
            --anim-duration: 4s;
            --surge-intensity: 0.8; 
            --b-scale-x: calc(1 - (0.2 * var(--surge-intensity)));
            --b-scale-y: calc(1 - (0.5 * var(--surge-intensity)));
            --f-rise: calc(-120px * var(--surge-intensity));
            --n-rot: calc(40deg + (120deg * var(--surge-intensity)));
        }

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

        body, html {
            width: 100%;
            height: 100%;
            background-color: var(--bg-base);
            color: var(--text-main);
            font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* 工业蓝图网格背景 */
        .grid-bg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-image: 
                linear-gradient(var(--bg-grid) 1px, transparent 1px),
                linear-gradient(90deg, var(--bg-grid) 1px, transparent 1px);
            background-size: 40px 40px;
            z-index: 0;
            opacity: 0.6;
        }

        /* CRT 扫描线特效 */
        .scanlines {
            position: absolute;
            top: 0; left: 0; width: 100%; height: 100%;
            background: linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0) 50%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.2));
            background-size: 100% 4px;
            z-index: 100;
            pointer-events: none;
            opacity: 0.3;
        }

        /* 布局容器 */
        .dashboard {
            position: relative;
            width: 100%;
            max-width: 1400px;
            height: 100%;
            max-height: 900px;
            z-index: 10;
            display: flex;
            flex-direction: column;
        }

        /* 浮动 HUD 文本信息面板 */
        .hud-panel {
            position: absolute;
            background: rgba(15, 23, 42, 0.85);
            border: 1px solid var(--steel);
            border-left: 3px solid var(--neon-cyan);
            padding: 16px 20px;
            backdrop-filter: blur(8px);
            box-shadow: 0 4px 20px rgba(0,0,0,0.5);
            z-index: 20;
        }
        
        .hud-top-left { top: 32px; left: 32px; border-left-color: var(--neon-amber); }
        .hud-top-right { top: 32px; right: 32px; }
        .hud-bottom-right { bottom: 32px; right: 32px; border-left-color: #10b981; }

        .hud-title {
            font-size: 14px;
            font-weight: 700;
            letter-spacing: 2px;
            color: var(--text-muted);
            margin-bottom: 12px;
            text-transform: uppercase;
        }

        .hud-data {
            font-family: 'Courier New', Courier, monospace;
            font-size: 13px;
            line-height: 1.6;
            color: var(--neon-cyan);
        }
        .hud-data .highlight { color: var(--neon-amber); font-weight: bold; }
        .hud-data .white { color: #fff; }

        /* 底部交互控制区 */
        .controls {
            position: absolute;
            bottom: 32px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(15, 23, 42, 0.9);
            border: 1px solid var(--steel);
            padding: 16px 32px;
            border-radius: 8px;
            display: flex;
            align-items: center;
            gap: 24px;
            z-index: 30;
            box-shadow: 0 0 30px rgba(0, 240, 255, 0.1);
        }

        .slider-group {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }

        .slider-group label {
            font-size: 12px;
            color: var(--text-muted);
            font-weight: 600;
        }

        input[type=range] {
            -webkit-appearance: none;
            width: 200px;
            background: var(--steel-dark);
            height: 4px;
            border-radius: 2px;
            outline: none;
        }
        input[type=range]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 16px;
            height: 16px;
            border-radius: 50%;
            background: var(--neon-cyan);
            cursor: pointer;
            box-shadow: 0 0 10px var(--neon-cyan);
            transition: transform 0.1s;
        }
        input[type=range]::-webkit-slider-thumb:hover {
            transform: scale(1.2);
        }

        /* SVG 动画核心区 */
        .svg-container {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            flex: 1;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1100px;
            overflow: visible;
        }

        /* ================= 核心 CSS 动画逻辑 ================= */
        
        /* 1. 流体脉冲波浪 (从左至右扫描) */
        @keyframes surge-wave {
            0% { transform: translateX(-300px); opacity: 0; }
            10% { opacity: 1; }
            80% { opacity: 1; }
            100% { transform: translateX(1100px); opacity: 0; }
        }
        .anim-surge {
            animation: surge-wave var(--anim-duration) infinite linear;
        }

        /* 2. 氮气囊形变 (与流体脉冲到达中点 53% 处同步) */
        @keyframes bladder-squish {
            0%, 35% { 
                transform: scale(1, 1); 
                fill: #d97706; /* 较暗的橙色,常态 */
                filter: drop-shadow(0 0 2px rgba(245, 158, 11, 0.2));
            }
            53% { 
                /* 根据冲击强度形变 */
                transform: scale(var(--b-scale-x), var(--b-scale-y)); 
                fill: var(--neon-amber); /* 高压时高亮发光 */
                filter: drop-shadow(0 0 15px var(--neon-amber));
            }
            75%, 100% { 
                transform: scale(1, 1); 
                fill: #d97706; 
                filter: drop-shadow(0 0 2px rgba(245, 158, 11, 0.2));
            }
        }
        .anim-bladder {
            transform-origin: 500px 110px; /* 锚定在顶部阀门处 */
            animation: bladder-squish var(--anim-duration) infinite ease-in-out;
            will-change: transform, fill, filter;
        }

        /* 3. 蓄能器内部流体液位上升 */
        @keyframes fluid-rise {
            0%, 35% { transform: translateY(0); }
            53% { transform: translateY(var(--f-rise)); } /* 冲入蓄能器 */
            75%, 100% { transform: translateY(0); }
        }
        .anim-fluid-level {
            animation: fluid-rise var(--anim-duration) infinite ease-in-out;
            will-change: transform;
        }

        /* 4. 压力表指针摆动 */
        @keyframes gauge-needle {
            0%, 35% { transform: rotate(40deg); }
            53% { transform: rotate(var(--n-rot)); } /* 压力飙升被抑制后的峰值 */
            75%, 100% { transform: rotate(40deg); }
        }
        .anim-needle {
            transform-origin: 350px 240px; /* 压力表圆心 */
            animation: gauge-needle var(--anim-duration) infinite ease-in-out;
            will-change: transform;
        }

        /* 5. 常规水流粒子流逝 (视差效果) */
        @keyframes flow-particles {
            0% { transform: translateX(0); }
            100% { transform: translateX(400px); }
        }
        .anim-particles {
            animation: flow-particles 2s infinite linear;
        }

        /* 微小呼吸灯 */
        @keyframes blink {
            0%, 100% { opacity: 0.3; }
            50% { opacity: 1; box-shadow: 0 0 10px #10b981; }
        }
        .status-light {
            animation: blink 2s infinite;
        }

    </style>
</head>
<body>
    <div class="grid-bg"></div>
    <div class="scanlines"></div>

    <div class="dashboard">
        <!-- 左上:原理阐述 -->
        <div class="hud-panel hud-top-left">
            <div class="hud-title">[ IFR 理想状态剖析 ]</div>
            <div class="hud-data">
                矛盾核心: <span class="white">大流量突变 → 管线水锤脉动破裂</span><br>
                理想解(IFR): <span class="highlight">零延迟、被动式自适应吸收</span><br>
                系统资源: <span class="white">利用流体自身的压力动能转化</span><br>
                核心部件: <span class="highlight">囊式蓄能器 (1.6L 容积)</span><br>
                工作介质: <span class="white">预充氮气 (充气压力 0.3MPa)</span>
            </div>
        </div>

        <!-- 右上:实时遥测数据模拟 -->
        <div class="hud-panel hud-top-right">
            <div class="hud-title">[ 实时管网遥测 TELEMETRY ]</div>
            <div class="hud-data">
                主进料管路压力: <span class="white" id="val-pipe-pres">0.31</span> MPa<br>
                瞬时脉冲波峰: <span class="highlight" id="val-peak-pres">+0.00</span> %<br>
                气囊形变吸收率: <span class="white" id="val-absorb">0</span> %<br>
                系统稳定性评价: <span style="color:#10b981;">运行平稳 (额定±10%内)</span>
            </div>
        </div>

        <!-- 右下:图例 -->
        <div class="hud-panel hud-bottom-right">
            <div class="hud-title">[ 图例说明 LEGEND ]</div>
            <div class="hud-data" style="display: flex; flex-direction: column; gap: 6px;">
                <div style="display: flex; align-items: center; gap: 8px;">
                    <div style="width: 12px; height: 12px; background: var(--neon-amber); border-radius: 2px;"></div> 氮气囊 (柔性可压缩)
                </div>
                <div style="display: flex; align-items: center; gap: 8px;">
                    <div style="width: 12px; height: 12px; background: #0284c7; border-radius: 2px;"></div> 进料管流体 (常态)
                </div>
                <div style="display: flex; align-items: center; gap: 8px;">
                    <div style="width: 12px; height: 12px; background: var(--neon-cyan); box-shadow: 0 0 5px var(--neon-cyan); border-radius: 2px;"></div> 高压水锤冲击波
                </div>
            </div>
        </div>

        <!-- 底部中央:交互控制 (动态修改 CSS 变量) -->
        <div class="controls">
            <div class="slider-group">
                <label for="intensitySlider">水锤冲击强度 (变量干预)</label>
                <input type="range" id="intensitySlider" min="0" max="1" step="0.05" value="0.8">
            </div>
            <div style="font-family: 'Courier New', monospace; font-size: 14px; color: var(--neon-cyan); font-weight: bold; width: 60px;" id="intensityVal">
                80%
            </div>
        </div>

        <!-- 中央 SVG 动画画布 -->
        <div class="svg-container">
            <svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet">
                <defs>
                    <!-- 滤镜与发光效果 -->
                    <filter id="neon-cyan" x="-50%" y="-50%" width="200%" height="200%">
                        <feGaussianBlur stdDeviation="8" result="blur1" />
                        <feGaussianBlur stdDeviation="20" result="blur2" />
                        <feMerge>
                            <feMergeNode in="blur2" />
                            <feMergeNode in="blur1" />
                            <feMergeNode in="SourceGraphic" />
                        </feMerge>
                    </filter>
                    
                    <filter id="neon-amber" x="-20%" y="-20%" width="140%" height="140%">
                        <feGaussianBlur stdDeviation="6" result="blur" />
                        <feComposite in="SourceGraphic" in2="blur" operator="over" />
                    </filter>

                    <!-- 渐变材质 -->
                    <linearGradient id="pipe-metal" x1="0%" y1="0%" x2="0%" y2="100%">
                        <stop offset="0%" stop-color="#334155" />
                        <stop offset="50%" stop-color="#0f172a" />
                        <stop offset="100%" stop-color="#1e293b" />
                    </linearGradient>
                    
                    <linearGradient id="fluid-grad" x1="0%" y1="0%" x2="0%" y2="100%">
                        <stop offset="0%" stop-color="#0ea5e9" />
                        <stop offset="100%" stop-color="#0284c7" stop-opacity="0.6"/>
                    </linearGradient>

                    <linearGradient id="surge-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                        <stop offset="0%" stop-color="rgba(0, 240, 255, 0)" />
                        <stop offset="50%" stop-color="rgba(0, 240, 255, 0.9)" />
                        <stop offset="100%" stop-color="rgba(0, 240, 255, 0)" />
                    </linearGradient>

                    <!-- 蓄能器内部裁剪蒙版 (限制流体只能在壳体内显示) -->
                    <clipPath id="acc-clip">
                        <!-- T型管与胶囊体合并轮廓 -->
                        <path d="M 430 350 L 430 180 C 430 140, 570 140, 570 180 L 570 350 Z" />
                    </clipPath>

                    <!-- 流动粒子 Pattern -->
                    <pattern id="particles" x="0" y="0" width="80" height="80" patternUnits="userSpaceOnUse">
                        <circle cx="20" cy="20" r="1.5" fill="#bae6fd" opacity="0.4"/>
                        <circle cx="60" cy="50" r="2" fill="#bae6fd" opacity="0.6"/>
                        <circle cx="40" cy="70" r="1" fill="#bae6fd" opacity="0.3"/>
                    </pattern>
                </defs>

                <!-- ================= 静态管路背景层 ================= -->
                <!-- 底部进料管基座轮廓 -->
                <path d="M 50 350 L 430 350 L 430 180 C 430 135, 570 135, 570 180 L 570 350 L 950 350" fill="none" stroke="#1e293b" stroke-width="16" />
                <path d="M 50 450 L 950 450" fill="none" stroke="#1e293b" stroke-width="16" />

                <!-- 管道外部金属线框,增加科技感 -->
                <path d="M 50 350 L 430 350 L 430 180 C 430 135, 570 135, 570 180 L 570 350 L 950 350" fill="none" stroke="var(--steel)" stroke-width="4" />
                <path d="M 50 450 L 950 450" fill="none" stroke="var(--steel)" stroke-width="4" />
                
                <!-- 法兰盘结构 -->
                <rect x="90" y="330" width="12" height="140" fill="var(--steel-dark)" stroke="var(--steel)" stroke-width="2" rx="2" />
                <rect x="898" y="330" width="12" height="140" fill="var(--steel-dark)" stroke="var(--steel)" stroke-width="2" rx="2" />

                <!-- ================= 流体及动画层 ================= -->
                
                <!-- 常态静态流体基础 (主管道) -->
                <rect x="50" y="352" width="900" height="96" fill="url(#fluid-grad)" />
                
                <!-- 蓄能器内部常态流体 (受裁剪区限制) -->
                <g clip-path="url(#acc-clip)">
                    <!-- 液位动画组,默认在下方,高压时向上平移 -->
                    <g class="anim-fluid-level">
                        <rect x="420" y="320" width="160" height="150" fill="#0284c7" />
                        <rect x="420" y="315" width="160" height="10" fill="#0ea5e9" opacity="0.8" /> <!-- 水面高光 -->
                    </g>
                </g>

                <!-- 水流粒子视差覆盖层 (表示流动方向) -->
                <g>
                    <rect x="50" y="352" width="1800" height="96" fill="url(#particles)" class="anim-particles" />
                </g>

                <!-- 水锤脉冲波浪 (核心动画1:从左至右冲刷) -->
                <rect x="0" y="352" width="300" height="96" fill="url(#surge-grad)" class="anim-surge" filter="url(#neon-cyan)" />

                <!-- ================= 蓄能器核心工作部件 ================= -->
                
                <!-- 气液缓冲蓄能器壳体 -->
                <path d="M 430 180 C 430 135, 570 135, 570 180 L 570 350 L 430 350 Z" fill="url(#pipe-metal)" fill-opacity="0.3" stroke="var(--neon-cyan-dim)" stroke-width="2" />
                
                <!-- 蓄能器内部尺寸刻度虚线 (设计感) -->
                <line x1="430" y1="200" x2="570" y2="200" stroke="rgba(255,255,255,0.1)" stroke-dasharray="4 4" />
                <line x1="430" y1="250" x2="570" y2="250" stroke="rgba(255,255,255,0.1)" stroke-dasharray="4 4" />
                <line x1="430" y1="300" x2="570" y2="300" stroke="rgba(255,255,255,0.1)" stroke-dasharray="4 4" />

                <!-- 氮气囊 Bladder (核心动画2:被挤压收缩) -->
                <!-- 锚点位于顶部中央(500, 110) -->
                <path d="M 500 110 
                         C 550 110, 560 160, 560 220 
                         C 560 290, 530 320, 500 320 
                         C 470 320, 440 290, 440 220 
                         C 440 160, 450 110, 500 110 Z" 
                      class="anim-bladder" />

                <!-- 顶部安全阀与充气口 -->
                <rect x="480" y="80" width="40" height="30" fill="var(--steel-dark)" stroke="var(--steel)" stroke-width="2" rx="4" />
                <path d="M 490 80 L 490 60 L 510 60 L 510 80" fill="none" stroke="var(--steel)" stroke-width="4" />
                <!-- 状态指示灯 (绿) -->
                <circle cx="500" cy="95" r="4" fill="#10b981" class="status-light" />

                <!-- ================= 仪表与细节 ================= -->
                
                <!-- 压力表组 -->
                <!-- 连接导管 -->
                <polyline points="430 240, 390 240, 390 240, 350 240" fill="none" stroke="var(--steel)" stroke-width="6" />
                <circle cx="350" cy="240" r="40" fill="var(--steel-dark)" stroke="var(--steel)" stroke-width="4" />
                <circle cx="350" cy="240" r="32" fill="#0f172a" />
                
                <!-- 刻度线 -->
                <g stroke="rgba(255,255,255,0.4)" stroke-width="2">
                    <line x1="350" y1="213" x2="350" y2="218" />
                    <line x1="323" y1="240" x2="328" y2="240" />
                    <line x1="350" y1="267" x2="350" y2="262" />
                    <line x1="377" y1="240" x2="372" y2="240" />
                    <line x1="331" y1="221" x2="334" y2="224" />
                    <line x1="369" y1="221" x2="366" y2="224" />
                </g>
                <text x="350" y="260" font-family="monospace" font-size="10" fill="var(--text-muted)" text-anchor="middle">MPa</text>

                <!-- 压力表指针 (核心动画3:指针摆动) -->
                <g class="anim-needle">
                    <circle cx="350" cy="240" r="4" fill="#ef4444" />
                    <line x1="350" y1="240" x2="350" y2="215" stroke="#ef4444" stroke-width="2" stroke-linecap="round" filter="url(#neon-amber)"/>
                </g>

                <!-- ================= 引导标注线 (文字细小,不遮挡动画) ================= -->
                <g fill="none" stroke="rgba(255,255,255,0.3)" stroke-width="1" stroke-dasharray="2 2">
                    <polyline points="650 180, 580 180, 540 220" />
                    <polyline points="250 400, 320 400" />
                </g>
                <g font-size="12" font-family="'Segoe UI', sans-serif" fill="var(--text-muted)">
                    <text x="655" y="184">高弹性氮气囊 (吸能主件)</text>
                    <text x="140" y="404">突发大流量水锤冲击区</text>
                    <text x="450" y="65">安全泄压阀</text>
                </g>
            </svg>
        </div>
    </div>

    <script>
        // JS 主要用于处理滑块交互,实时更新CSS变量,以及遥测数据的动态数字效果
        // 核心动画严格由原生 CSS @keyframes 驱动,确保自动播放及流畅度
        
        document.addEventListener('DOMContentLoaded', () => {
            const slider = document.getElementById('intensitySlider');
            const intensityText = document.getElementById('intensityVal');
            
            const root = document.documentElement;
            
            // HUD 遥测数值元素
            const peakPres = document.getElementById('val-peak-pres');
            const absorbRate = document.getElementById('val-absorb');
            const pipePres = document.getElementById('val-pipe-pres');

            // 监听滑块更新
            function updateIntensity() {
                const val = parseFloat(slider.value);
                intensityText.textContent = Math.round(val * 100) + '%';
                
                // 将强度传导给 CSS Custom Properties,CSS @keyframes 会实时响应
                root.style.setProperty('--surge-intensity', val);
            }

            slider.addEventListener('input', updateIntensity);
            
            // 遥测数据动态模拟动画,增加高保真科技感
            // 使用 requestAnimationFrame 与 CSS 动画周期同步 (动画周期 4s)
            let startT = null;
            const durationMs = 4000;

            function animateTelemetry(timestamp) {
                if (!startT) startT = timestamp;
                const elapsed = timestamp - startT;
                const progress = (elapsed % durationMs) / durationMs; 
                
                // 根据 progress (0~1) 模拟动画周期:
                // 0~0.35 正常, 0.35~0.53 冲击(峰值), 0.53~0.75 恢复, 0.75~1.0 正常
                
                let baseP = 0.30;
                let surgeFactor = parseFloat(slider.value);
                
                if (progress > 0.35 && progress < 0.75) {
                    // 构造一个在 0.53 时达到顶峰的抛物线/三角函数波
                    let spike = 0;
                    if (progress <= 0.53) {
                        spike = (progress - 0.35) / 0.18; // 0 to 1
                    } else {
                        spike = 1 - ((progress - 0.53) / 0.22); // 1 to 0
                    }
                    
                    // 模拟数值跳动
                    let jitter = (Math.random() * 0.02) - 0.01;
                    
                    let currentPres = baseP + (0.15 * surgeFactor * spike) + jitter;
                    pipePres.textContent = currentPres.toFixed(2);
                    
                    let overload = (currentPres - baseP) / baseP * 100;
                    peakPres.textContent = "+" + Math.max(0, overload).toFixed(1);
                    
                    // 吸收率与形变挂钩
                    let absorb = Math.min(99, spike * surgeFactor * 85 + (Math.random()*5));
                    absorbRate.textContent = absorb.toFixed(1);
                    
                } else {
                    // 常态轻微波动
                    let jitter = (Math.random() * 0.01) - 0.005;
                    pipePres.textContent = (baseP + jitter).toFixed(2);
                    peakPres.textContent = "+0.0";
                    absorbRate.textContent = "0.0";
                }

                requestAnimationFrame(animateTelemetry);
            }
            
            // 启动数字同步动画
            requestAnimationFrame(animateTelemetry);
            
            // 确保初始状态同步
            updateIntensity();
        });
    </script>
</body>
</html>

这段代码通过纯 CSS 关键帧技术严格实现了连续运行的水锤脉动和气液蓄能器动态模拟,页面加载完成后即可自动运行。采用深色工业科技主题,主控动画区域居中且无大面积文字遮挡,完美符合并突出了基于 TRIZ 的“零延迟、利用现有压力资源被动吸能”的最终理想解 (IFR) 原理展示。可交互的底部滑块能动态改变核心吸收逻辑的形变参数,增加探索性。

积分规则:每轮对话扣10分