分享图
动画工坊
引擎就绪
<!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-color: #05080f;
            --grid-color: #111a2e;
            --fluid-color: #A3E635; /* Viscous drilling fluid */
            --fluid-dim: rgba(163, 230, 53, 0.3);
            --air-color: #00F0FF;   /* Pneumatic power */
            --metal-light: #94A3B8;
            --metal-dark: #334155;
            --accent: #FF6B35;      /* Mechanical moving parts focus */
            --text-muted: #64748B;
        }

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

        body {
            background-color: var(--bg-color);
            color: var(--metal-light);
            font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100vw;
        }

        /* Minimal UI Overlay */
        .ui-panel {
            position: absolute;
            pointer-events: none;
            z-index: 10;
        }

        .ui-top-left {
            top: 24px;
            left: 24px;
            max-width: 340px;
        }

        .ui-title {
            font-size: 14px;
            font-weight: 700;
            color: #fff;
            letter-spacing: 1px;
            margin-bottom: 6px;
            text-transform: uppercase;
        }

        .ui-desc {
            font-size: 11px;
            line-height: 1.6;
            color: var(--text-muted);
        }

        .ui-desc span {
            color: var(--air-color);
            font-weight: 600;
        }

        /* Controls */
        .controls-container {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            align-items: center;
            gap: 16px;
            background: rgba(15, 23, 42, 0.7);
            backdrop-filter: blur(8px);
            padding: 10px 24px;
            border-radius: 30px;
            border: 1px solid var(--metal-dark);
            z-index: 20;
        }

        .play-btn {
            background: none;
            border: none;
            color: var(--air-color);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 4px;
            transition: transform 0.2s;
        }

        .play-btn:hover {
            transform: scale(1.1);
        }

        .play-btn svg {
            width: 20px;
            height: 20px;
            fill: currentColor;
        }

        .slider-wrapper {
            display: flex;
            align-items: center;
            gap: 12px;
            width: 300px;
        }

        input[type=range] {
            -webkit-appearance: none;
            width: 100%;
            background: transparent;
        }

        input[type=range]::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 12px;
            width: 12px;
            border-radius: 50%;
            background: var(--air-color);
            cursor: pointer;
            margin-top: -5px;
            box-shadow: 0 0 10px var(--air-color);
        }

        input[type=range]::-webkit-slider-runnable-track {
            width: 100%;
            height: 2px;
            cursor: pointer;
            background: var(--metal-dark);
            border-radius: 1px;
        }

        .slider-label {
            font-size: 10px;
            color: var(--text-muted);
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }

        /* SVG Styles */
        svg.main-stage {
            width: 100%;
            height: 100%;
            max-width: 1600px;
        }

        .blueprint-text {
            font-family: ui-monospace, SFMono-Regular, monospace;
            font-size: 11px;
            fill: var(--text-muted);
            letter-spacing: 0.5px;
        }

        .highlight-text {
            fill: var(--air-color);
            font-weight: bold;
        }

        .grid-line {
            stroke: var(--grid-color);
            stroke-width: 1;
        }

        .component {
            fill: var(--bg-color);
            stroke: var(--metal-light);
            stroke-width: 2;
        }

        .component-dark {
            fill: var(--metal-dark);
            stroke: var(--metal-light);
            stroke-width: 1;
        }

        .fluid {
            fill: var(--fluid-color);
            transition: fill 0.3s;
        }

        .fluid-line {
            stroke: var(--fluid-color);
            stroke-width: 4;
            stroke-linecap: round;
            fill: none;
        }

        .air-line {
            stroke: var(--metal-dark);
            stroke-width: 3;
            fill: none;
            stroke-dasharray: 4 4;
            transition: stroke 0.3s, filter 0.3s;
        }

        .air-line.active {
            stroke: var(--air-color);
            filter: drop-shadow(0 0 5px var(--air-color));
            animation: dashMove 0.5s linear infinite;
        }

        .mechanical-link {
            stroke: var(--accent);
            stroke-width: 3;
            stroke-linecap: round;
            fill: none;
        }

        .pivot {
            fill: var(--accent);
            stroke: var(--bg-color);
            stroke-width: 2;
        }

        .wire-rope {
            stroke: var(--metal-light);
            stroke-width: 1.5;
            stroke-dasharray: 6 3;
            fill: none;
        }

        .glow {
            filter: drop-shadow(0 0 8px var(--fluid-dim));
        }

        @keyframes dashMove {
            to { stroke-dashoffset: -8; }
        }
    </style>
</head>
<body>

    <!-- Minimal UI Annotations -->
    <div class="ui-panel ui-top-left">
        <div class="ui-title">最终理想解 (IFR) · 止流自适应机构</div>
        <div class="ui-desc">
            采用 TRIZ 思想剥离对外部电源与弱电控制的依赖。以现场气源为动力,利用流体势能(浮力)作为唯一感知输入。<br><br>
            机械连杆 1:2 放大浮球行程,直接驱动 <span>气控换向阀</span> 抬升筛面并联动堰板减流。缓冲罐满载时,纯机械联动开启底端泄流阀。全过程 0 电子元件。
        </div>
    </div>

    <!-- Interactive Controls -->
    <div class="controls-container">
        <button class="play-btn" id="playBtn" title="Play/Pause">
            <!-- Pause Icon Default -->
            <svg id="icon-pause" viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
            <svg id="icon-play" viewBox="0 0 24 24" style="display:none;"><path d="M8 5v14l11-7z"/></svg>
        </button>
        <div class="slider-wrapper">
            <span class="slider-label">CYCLE</span>
            <input type="range" id="timeline" min="0" max="100" value="0" step="0.1">
            <span class="slider-label" id="phase-label">0%</span>
        </div>
    </div>

    <!-- Main SVG Animation Stage -->
    <svg class="main-stage" viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid meet">
        <!-- Definitions for grids and filters -->
        <defs>
            <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                <path d="M 40 0 L 0 0 0 40" class="grid-line" />
            </pattern>
            <linearGradient id="fluidGrad" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stop-color="#A3E635" stop-opacity="0.8"/>
                <stop offset="100%" stop-color="#65a30d" stop-opacity="0.9"/>
            </linearGradient>
            <clipPath id="screenClip">
                <rect x="310" y="310" width="380" height="70" rx="4" />
            </clipPath>
            <clipPath id="tankClip">
                <rect x="750" y="550" width="260" height="200" rx="8" />
            </clipPath>
            <filter id="neonAir" x="-20%" y="-20%" width="140%" height="140%">
                <feGaussianBlur stdDeviation="4" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
        </defs>

        <!-- Background Grid -->
        <rect width="100%" height="100%" fill="url(#grid)" />

        <!-- STATIC BACKGROUND ELEMENTS -->
        <g id="static-layer">
            <!-- Inlet Pipe -->
            <path d="M220,-10 L220,180 L280,180 L280,-10" class="component" />
            <!-- Main Pivot Base -->
            <path d="M720,400 L740,450 L700,450 Z" class="component-dark" />
            <!-- Air Supply Point -->
            <rect x="80" y="550" width="60" height="30" rx="4" class="component-dark" />
            <text x="110" y="570" class="blueprint-text" text-anchor="middle">0.7MPa气源</text>
            <!-- Buffer Tank Outline -->
            <rect x="750" y="550" width="260" height="200" rx="8" class="component" />
            <path d="M1010,700 L1070,700 L1070,740 L1010,740 Z" class="component" /> <!-- Drain Pipe -->
            <!-- Wire Rope Pulleys -->
            <circle cx="290" cy="100" r="10" class="component-dark" />
            <circle cx="260" cy="100" r="10" class="component-dark" />
        </g>

        <!-- DYNAMIC ELEMENTS (Controlled by JS) -->
        <g id="dynamic-layer">
            
            <!-- Inflow Fluid -->
            <path id="inlet-fluid" d="M230,180 L270,180 L270,320 L230,320 Z" fill="url(#fluidGrad)" class="glow" />
            
            <!-- Weir Plate (Slides Y) -->
            <rect id="weir-plate" x="275" y="100" width="10" height="90" rx="2" class="component" fill="#cbd5e1" />

            <!-- Dump Fluid (Screen to Tank) -->
            <path id="dump-fluid" d="M710,380 Q760,380 770,550 L790,550 Q780,390 710,390 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
            
            <!-- Drain Fluid (Tank Out) -->
            <path id="drain-fluid" d="M1040,740 L1070,740 L1070,850 L1040,850 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />

            <!-- SCREEN GROUP (Rotates around Pivot 720, 390) -->
            <g id="screen-group" transform="rotate(0, 720, 390)">
                <!-- Screen Box -->
                <rect x="300" y="300" width="420" height="90" rx="6" class="component" />
                <line x1="310" y1="380" x2="710" y2="380" stroke="#334155" stroke-width="4" stroke-dasharray="8 4" /> <!-- Screen mesh -->
                
                <!-- Screen Liquid -->
                <g clip-path="url(#screenClip)">
                    <rect id="screen-liquid" x="310" y="380" width="380" height="0" fill="url(#fluidGrad)" class="glow" />
                </g>
                
                <!-- Float 1 & Internal Linkage -->
                <circle id="float1" cx="380" cy="380" r="16" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
                <!-- Lever connected to float1 -->
                <line id="lever1" x1="380" y1="380" x2="460" y2="250" class="mechanical-link" />
                <circle cx="430" cy="300" r="4" class="pivot" /> <!-- Pivot for Lever 1 -->
            </g>
            <circle cx="720" cy="390" r="8" class="pivot" /> <!-- Main Screen Pivot -->

            <!-- PNEUMATIC SYSTEM -->
            <!-- Air Valve -->
            <rect x="440" y="230" width="40" height="40" rx="4" class="component-dark" />
            <text x="460" y="215" class="blueprint-text" text-anchor="middle">气控换向阀</text>
            
            <!-- Air Lines -->
            <path id="air-line-in" d="M140,565 L180,565 L180,250 L440,250" class="air-line" />
            <path id="air-line-out" d="M480,250 L520,250 L520,620 L330,620 L330,580" class="air-line" />

            <!-- Pneumatic Cylinder -->
            <rect x="290" y="480" width="40" height="100" rx="4" class="component-dark" />
            <rect id="cylinder-rod" x="302" y="380" width="16" height="100" class="component" fill="#e2e8f0" />
            <circle id="cylinder-pin" cx="310" cy="380" r="5" class="pivot" />
            <text x="260" y="530" class="blueprint-text" text-anchor="end">升降气缸</text>

            <!-- Wire Rope Mechanism (Linked to Cylinder Rod) -->
            <path id="wire-rope" d="M310,380 L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,100" class="wire-rope" />

            <!-- BUFFER TANK SYSTEM -->
            <!-- Tank Liquid -->
            <g clip-path="url(#tankClip)">
                <rect id="tank-liquid" x="750" y="750" width="260" height="0" fill="url(#fluidGrad)" class="glow" />
            </g>

            <!-- Float 2 & Butterfly Valve Linkage -->
            <circle id="float2" cx="820" cy="730" r="20" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
            <line id="lever2" x1="820" y1="730" x2="1040" y2="650" class="mechanical-link" />
            <circle cx="950" cy="682" r="5" class="pivot" /> <!-- Pivot for Lever 2 -->

            <!-- Butterfly Valve Assembly -->
            <circle cx="1040" cy="720" r="24" class="component-dark" />
            <line id="valve-disc" x1="1040" y1="696" x2="1040" y2="744" stroke="#e2e8f0" stroke-width="6" stroke-linecap="round" />
            <text x="1100" y="725" class="blueprint-text highlight-text">纯机械联动蝶阀</text>

        </g>

        <!-- STATIC FOREGROUND ANNOTATIONS -->
        <g id="annotations">
            <!-- Screen Lift annotation -->
            <line x1="160" y1="390" x2="280" y2="390" class="grid-line" stroke-dasharray="4" />
            <path d="M220,390 L220,330" stroke="var(--text-muted)" stroke-width="1" marker-end="url(#arrow)" />
            <text x="210" y="360" class="blueprint-text" text-anchor="end">抬升 100mm</text>
            
            <!-- Float action annotation -->
            <path d="M420,430 L380,430 L380,396" stroke="var(--text-muted)" stroke-width="1" fill="none" />
            <text x="430" y="434" class="blueprint-text">液位行程 250mm</text>
            
            <!-- Mechanical Ratio -->
            <text x="430" y="280" class="blueprint-text">放大比 1:2</text>
            <text x="880" y="660" class="blueprint-text">放大比联动</text>
        </g>

        <defs>
            <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--text-muted)" />
            </marker>
        </defs>
    </svg>

    <script>
        /**
         * Animation Math & Logic
         * Driven by a 0-100 master timeline loop
         */
        const state = {
            t: 0,
            playing: true,
            speed: 0.15
        };

        // DOM Elements
        const els = {
            inlet_fluid: document.getElementById('inlet-fluid'),
            weir_plate: document.getElementById('weir-plate'),
            screen_group: document.getElementById('screen-group'),
            screen_liquid: document.getElementById('screen-liquid'),
            float1: document.getElementById('float1'),
            lever1: document.getElementById('lever1'),
            air_line_in: document.getElementById('air-line-in'),
            air_line_out: document.getElementById('air-line-out'),
            cylinder_rod: document.getElementById('cylinder-rod'),
            cylinder_pin: document.getElementById('cylinder-pin'),
            wire_rope: document.getElementById('wire-rope'),
            dump_fluid: document.getElementById('dump-fluid'),
            tank_liquid: document.getElementById('tank-liquid'),
            float2: document.getElementById('float2'),
            lever2: document.getElementById('lever2'),
            valve_disc: document.getElementById('valve-disc'),
            drain_fluid: document.getElementById('drain-fluid'),
            timeline: document.getElementById('timeline'),
            phase_label: document.getElementById('phase-label'),
            play_btn: document.getElementById('playBtn'),
            icon_play: document.getElementById('icon-play'),
            icon_pause: document.getElementById('icon-pause')
        };

        // Easing functions for mechanical realism
        function easeInOutQuad(x) {
            return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
        }

        // Map a time segment to a 0-1 value
        function mapTime(t, start, end) {
            if (t <= start) return 0;
            if (t >= end) return 1;
            return easeInOutQuad((t - start) / (end - start));
        }

        function updateFrame() {
            let t = state.t; // 0 to 100

            // 1. Inflow fills screen (0-20), then drains (40-60)
            let L1_fill = mapTime(t, 0, 20);
            let L1_drain = mapTime(t, 40, 60);
            let L1 = L1_fill - L1_drain; // 0.0 to 1.0

            // 2. Float 1 directly follows L1 mechanically
            let F1 = L1;

            // 3. Pneumatic Valve triggers when F1 > 0.8. 
            // Cylinder actuates (20-35), drops (75-90)
            let airOn = (t > 18 && t < 78);
            let C1_up = mapTime(t, 20, 35);
            let C1_down = mapTime(t, 75, 90);
            let C1 = C1_up - C1_down; // 0.0 to 1.0

            // 4. Fluid flow from screen to tank happens when screen is lifted
            let dump_active = (t > 38 && t < 65);
            
            // 5. Tank fills (40-65), drains (65-85)
            let L2_fill = mapTime(t, 40, 65);
            let L2_drain = mapTime(t, 65, 85);
            let L2 = L2_fill - L2_drain; // 0.0 to 1.0

            // 6. Tank Float directly follows L2
            let F2 = L2;

            // 7. Valve Disc linked to F2
            let V1 = F2;

            // --- DOM UPDATES ---

            // Screen Liquid Height (Max 65px)
            let liquidH = L1 * 65;
            els.screen_liquid.setAttribute('y', 380 - liquidH);
            els.screen_liquid.setAttribute('height', liquidH);

            // Screen Float 1 (Moves up with liquid)
            let f1_y = 364 - liquidH;
            els.float1.setAttribute('cy', f1_y);
            
            // Lever 1 Rotation based on F1
            let lever1_angle = -F1 * 25; // max 25 deg up
            els.lever1.setAttribute('transform', `rotate(${lever1_angle}, 430, 300)`);
            // Connect line end to float (simplified local rotation logic)
            // The float center moves, the rod stretches/rotates. Using SVG transforms makes this easier.
            // For visual precision, just letting it point is enough for the principle.

            // Air Logic
            if (airOn) {
                els.air_line_in.classList.add('active');
                els.air_line_out.classList.add('active');
            } else {
                els.air_line_in.classList.remove('active');
                els.air_line_out.classList.remove('active');
            }

            // Cylinder Extends (Max 60px)
            let cyl_ext = C1 * 60;
            els.cylinder_rod.setAttribute('y', 380 - cyl_ext);
            els.cylinder_rod.setAttribute('height', 100 + cyl_ext);
            els.cylinder_pin.setAttribute('cy', 380 - cyl_ext);

            // Screen Box Tilt (Max 12 deg)
            let screen_angle = C1 * 12;
            els.screen_group.setAttribute('transform', `rotate(${-screen_angle}, 720, 390)`);

            // Weir Plate & Wire Rope (closes 50% = drops 45px)
            let weir_drop = C1 * 45;
            els.weir_plate.setAttribute('transform', `translate(0, ${weir_drop})`);
            
            // Adjust Inlet fluid visual based on weir
            if (weir_drop > 0) {
                els.inlet_fluid.setAttribute('d', `M230,${180+weir_drop} L270,${180+weir_drop} L270,320 L230,320 Z`);
            } else {
                els.inlet_fluid.setAttribute('d', `M230,180 L270,180 L270,320 L230,320 Z`);
            }

            // Dynamic Wire Rope Path
            // Cylinder pin is at (310, 380 - cyl_ext). Pulley 1 at (290, 100), Pulley 2 at (260, 100). Weir at (280, 100 + weir_drop)
            els.wire_rope.setAttribute('d', `M310,${380 - cyl_ext} L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,${100 + weir_drop}`);

            // Dump Fluid Appearance
            els.dump_fluid.setAttribute('opacity', dump_active ? (C1 * 0.9) : 0);

            // Tank Liquid Height (Max 150px)
            let tank_liquidH = L2 * 150;
            els.tank_liquid.setAttribute('y', 750 - tank_liquidH);
            els.tank_liquid.setAttribute('height', tank_liquidH);

            // Tank Float 2
            let f2_y = 730 - tank_liquidH;
            els.float2.setAttribute('cy', f2_y);

            // Lever 2 Rotation (Pivot 950, 682)
            // Lever maps from float to valve. 
            let lever2_angle = -F2 * 35; 
            els.lever2.setAttribute('transform', `rotate(${lever2_angle}, 950, 682)`);
            els.lever2.setAttribute('y1', f2_y);

            // Butterfly Valve Disc Rotation (0 to 90deg)
            let valve_angle = V1 * 90;
            els.valve_disc.setAttribute('transform', `rotate(${valve_angle}, 1040, 720)`);

            // Drain Fluid Appearance
            els.drain_fluid.setAttribute('opacity', V1 > 0.1 ? V1 : 0);

            // UI Updates
            if (state.playing) {
                els.timeline.value = t;
                els.phase_label.innerText = Math.floor(t) + '%';
            }
        }

        function loop() {
            if (state.playing) {
                state.t += state.speed;
                if (state.t > 100) state.t = 0;
                updateFrame();
            }
            requestAnimationFrame(loop);
        }

        // Interactivity
        els.timeline.addEventListener('input', (e) => {
            state.t = parseFloat(e.target.value);
            els.phase_label.innerText = Math.floor(state.t) + '%';
            updateFrame();
        });

        els.timeline.addEventListener('mousedown', () => { state.playing = false; updatePlayBtn(); });
        els.timeline.addEventListener('mouseup', () => { state.playing = true; updatePlayBtn(); });

        els.play_btn.addEventListener('click', () => {
            state.playing = !state.playing;
            updatePlayBtn();
        });

        function updatePlayBtn() {
            if(state.playing) {
                els.icon_pause.style.display = 'block';
                els.icon_play.style.display = 'none';
            } else {
                els.icon_pause.style.display = 'none';
                els.icon_play.style.display = 'block';
            }
        }

        // Auto-start on load
        window.addEventListener('DOMContentLoaded', () => {
            state.t = 0;
            state.playing = true;
            updatePlayBtn();
            loop();
        });

    </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-color: #ffffff;
            --grid-color: #e2e8f0;
            --fluid-color: #84cc16; /* 稍微加深以适应白底 */
            --fluid-dim: rgba(132, 204, 22, 0.3);
            --air-color: #0284c7;   /* 加深的气动蓝色,确保在白底上清晰 */
            --metal-light: #94a3b8;
            --metal-dark: #334155;
            --accent: #ea580c;      /* 加深的机械运动件强调色 */
            --text-muted: #64748b;
        }

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

        body {
            background-color: var(--bg-color);
            color: var(--metal-light);
            font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            width: 100vw;
        }

        /* Minimal UI Overlay */
        .ui-panel {
            position: absolute;
            pointer-events: none;
            z-index: 10;
        }

        .ui-top-left {
            top: 24px;
            left: 24px;
            max-width: 340px;
        }

        .ui-title {
            font-size: 14px;
            font-weight: 700;
            color: #0f172a; /* 适配白底的深色标题 */
            letter-spacing: 1px;
            margin-bottom: 6px;
            text-transform: uppercase;
        }

        .ui-desc {
            font-size: 11px;
            line-height: 1.6;
            color: var(--text-muted);
        }

        .ui-desc span {
            color: var(--air-color);
            font-weight: 600;
        }

        /* Controls */
        .controls-container {
            position: absolute;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            align-items: center;
            gap: 16px;
            background: rgba(255, 255, 255, 0.8); /* 适配白底的半透明面板 */
            backdrop-filter: blur(8px);
            padding: 10px 24px;
            border-radius: 30px;
            border: 1px solid var(--grid-color);
            z-index: 20;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }

        .play-btn {
            background: none;
            border: none;
            color: var(--air-color);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 4px;
            transition: transform 0.2s;
        }

        .play-btn:hover {
            transform: scale(1.1);
        }

        .play-btn svg {
            width: 20px;
            height: 20px;
            fill: currentColor;
        }

        .slider-wrapper {
            display: flex;
            align-items: center;
            gap: 12px;
            width: 300px;
        }

        input[type=range] {
            -webkit-appearance: none;
            width: 100%;
            background: transparent;
        }

        input[type=range]::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 12px;
            width: 12px;
            border-radius: 50%;
            background: var(--air-color);
            cursor: pointer;
            margin-top: -5px;
            box-shadow: 0 0 10px var(--air-color);
        }

        input[type=range]::-webkit-slider-runnable-track {
            width: 100%;
            height: 2px;
            cursor: pointer;
            background: var(--metal-light); /* 适配白底 */
            border-radius: 1px;
        }

        .slider-label {
            font-size: 10px;
            color: var(--text-muted);
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
        }

        /* SVG Styles */
        svg.main-stage {
            width: 100%;
            height: 100%;
            max-width: 1600px;
        }

        .blueprint-text {
            font-family: ui-monospace, SFMono-Regular, monospace;
            font-size: 11px;
            fill: var(--text-muted);
            letter-spacing: 0.5px;
        }

        .highlight-text {
            fill: var(--air-color);
            font-weight: bold;
        }

        .grid-line {
            stroke: var(--grid-color);
            stroke-width: 1;
        }

        .component {
            fill: var(--bg-color);
            stroke: var(--metal-light);
            stroke-width: 2;
        }

        .component-dark {
            fill: var(--metal-dark);
            stroke: var(--metal-light);
            stroke-width: 1;
        }

        .fluid {
            fill: var(--fluid-color);
            transition: fill 0.3s;
        }

        .fluid-line {
            stroke: var(--fluid-color);
            stroke-width: 4;
            stroke-linecap: round;
            fill: none;
        }

        .air-line {
            stroke: var(--metal-dark);
            stroke-width: 3;
            fill: none;
            stroke-dasharray: 4 4;
            transition: stroke 0.3s, filter 0.3s;
        }

        .air-line.active {
            stroke: var(--air-color);
            filter: drop-shadow(0 0 3px var(--air-color));
            animation: dashMove 0.5s linear infinite;
        }

        .mechanical-link {
            stroke: var(--accent);
            stroke-width: 3;
            stroke-linecap: round;
            fill: none;
        }

        .pivot {
            fill: var(--accent);
            stroke: var(--bg-color);
            stroke-width: 2;
        }

        .wire-rope {
            stroke: var(--metal-light);
            stroke-width: 1.5;
            stroke-dasharray: 6 3;
            fill: none;
        }

        .glow {
            filter: drop-shadow(0 0 8px var(--fluid-dim));
        }

        @keyframes dashMove {
            to { stroke-dashoffset: -8; }
        }
    </style>
</head>
<body>

    <!-- Minimal UI Annotations -->
    <div class="ui-panel ui-top-left">
        <div class="ui-title">最终理想解 (IFR) · 止流自适应机构</div>
        <div class="ui-desc">
            采用 TRIZ 思想剥离对外部电源与弱电控制的依赖。以现场气源为动力,利用流体势能(浮力)作为唯一感知输入。<br><br>
            机械连杆 1:2 放大浮球行程,直接驱动 <span>气控换向阀</span> 抬升筛面并联动堰板减流。缓冲罐满载时,纯机械联动开启底端泄流阀。全过程 0 电子元件。
        </div>
    </div>

    <!-- Interactive Controls -->
    <div class="controls-container">
        <button class="play-btn" id="playBtn" title="Play/Pause">
            <!-- Pause Icon Default -->
            <svg id="icon-pause" viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
            <svg id="icon-play" viewBox="0 0 24 24" style="display:none;"><path d="M8 5v14l11-7z"/></svg>
        </button>
        <div class="slider-wrapper">
            <span class="slider-label">CYCLE</span>
            <input type="range" id="timeline" min="0" max="100" value="0" step="0.1">
            <span class="slider-label" id="phase-label">0%</span>
        </div>
    </div>

    <!-- Main SVG Animation Stage -->
    <svg class="main-stage" viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid meet">
        <!-- Definitions for grids and filters -->
        <defs>
            <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                <path d="M 40 0 L 0 0 0 40" class="grid-line" />
            </pattern>
            <linearGradient id="fluidGrad" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stop-color="#84cc16" stop-opacity="0.8"/>
                <stop offset="100%" stop-color="#65a30d" stop-opacity="0.9"/>
            </linearGradient>
            <clipPath id="screenClip">
                <rect x="310" y="310" width="380" height="70" rx="4" />
            </clipPath>
            <clipPath id="tankClip">
                <rect x="750" y="550" width="260" height="200" rx="8" />
            </clipPath>
            <filter id="neonAir" x="-20%" y="-20%" width="140%" height="140%">
                <feGaussianBlur stdDeviation="4" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>
        </defs>

        <!-- Background Grid -->
        <rect width="100%" height="100%" fill="url(#grid)" />

        <!-- STATIC BACKGROUND ELEMENTS -->
        <g id="static-layer">
            <!-- Inlet Pipe -->
            <path d="M220,-10 L220,180 L280,180 L280,-10" class="component" />
            <!-- Main Pivot Base -->
            <path d="M720,400 L740,450 L700,450 Z" class="component-dark" />
            <!-- Air Supply Point -->
            <rect x="80" y="550" width="60" height="30" rx="4" class="component-dark" />
            <text x="110" y="570" class="blueprint-text" fill="#f8fafc" text-anchor="middle">0.7MPa气源</text>
            <!-- Buffer Tank Outline -->
            <rect x="750" y="550" width="260" height="200" rx="8" class="component" />
            <path d="M1010,700 L1070,700 L1070,740 L1010,740 Z" class="component" /> <!-- Drain Pipe -->
            <!-- Wire Rope Pulleys -->
            <circle cx="290" cy="100" r="10" class="component-dark" />
            <circle cx="260" cy="100" r="10" class="component-dark" />
        </g>

        <!-- DYNAMIC ELEMENTS (Controlled by JS) -->
        <g id="dynamic-layer">
            
            <!-- Inflow Fluid -->
            <path id="inlet-fluid" d="M230,180 L270,180 L270,320 L230,320 Z" fill="url(#fluidGrad)" class="glow" />
            
            <!-- Weir Plate (Slides Y) -->
            <rect id="weir-plate" x="275" y="100" width="10" height="90" rx="2" class="component" fill="#cbd5e1" />

            <!-- Dump Fluid (Screen to Tank) -->
            <path id="dump-fluid" d="M710,380 Q760,380 770,550 L790,550 Q780,390 710,390 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
            
            <!-- Drain Fluid (Tank Out) -->
            <path id="drain-fluid" d="M1040,740 L1070,740 L1070,850 L1040,850 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />

            <!-- SCREEN GROUP (Rotates around Pivot 720, 390) -->
            <g id="screen-group" transform="rotate(0, 720, 390)">
                <!-- Screen Box -->
                <rect x="300" y="300" width="420" height="90" rx="6" class="component" />
                <line x1="310" y1="380" x2="710" y2="380" stroke="#334155" stroke-width="4" stroke-dasharray="8 4" /> <!-- Screen mesh -->
                
                <!-- Screen Liquid -->
                <g clip-path="url(#screenClip)">
                    <rect id="screen-liquid" x="310" y="380" width="380" height="0" fill="url(#fluidGrad)" class="glow" />
                </g>
                
                <!-- Float 1 & Internal Linkage -->
                <circle id="float1" cx="380" cy="380" r="16" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
                <!-- Lever connected to float1 -->
                <line id="lever1" x1="380" y1="380" x2="460" y2="250" class="mechanical-link" />
                <circle cx="430" cy="300" r="4" class="pivot" /> <!-- Pivot for Lever 1 -->
            </g>
            <circle cx="720" cy="390" r="8" class="pivot" /> <!-- Main Screen Pivot -->

            <!-- PNEUMATIC SYSTEM -->
            <!-- Air Valve -->
            <rect x="440" y="230" width="40" height="40" rx="4" class="component-dark" />
            <text x="460" y="215" class="blueprint-text" text-anchor="middle">气控换向阀</text>
            
            <!-- Air Lines -->
            <path id="air-line-in" d="M140,565 L180,565 L180,250 L440,250" class="air-line" />
            <path id="air-line-out" d="M480,250 L520,250 L520,620 L330,620 L330,580" class="air-line" />

            <!-- Pneumatic Cylinder -->
            <rect x="290" y="480" width="40" height="100" rx="4" class="component-dark" />
            <rect id="cylinder-rod" x="302" y="380" width="16" height="100" class="component" fill="#f8fafc" />
            <circle id="cylinder-pin" cx="310" cy="380" r="5" class="pivot" />
            <text x="260" y="530" class="blueprint-text" text-anchor="end">升降气缸</text>

            <!-- Wire Rope Mechanism (Linked to Cylinder Rod) -->
            <path id="wire-rope" d="M310,380 L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,100" class="wire-rope" />

            <!-- BUFFER TANK SYSTEM -->
            <!-- Tank Liquid -->
            <g clip-path="url(#tankClip)">
                <rect id="tank-liquid" x="750" y="750" width="260" height="0" fill="url(#fluidGrad)" class="glow" />
            </g>

            <!-- Float 2 & Butterfly Valve Linkage -->
            <circle id="float2" cx="820" cy="730" r="20" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
            <line id="lever2" x1="820" y1="730" x2="1040" y2="650" class="mechanical-link" />
            <circle cx="950" cy="682" r="5" class="pivot" /> <!-- Pivot for Lever 2 -->

            <!-- Butterfly Valve Assembly -->
            <circle cx="1040" cy="720" r="24" class="component-dark" />
            <line id="valve-disc" x1="1040" y1="696" x2="1040" y2="744" stroke="#94a3b8" stroke-width="6" stroke-linecap="round" />
            <text x="1100" y="725" class="blueprint-text highlight-text">纯机械联动蝶阀</text>

        </g>

        <!-- STATIC FOREGROUND ANNOTATIONS -->
        <g id="annotations">
            <!-- Screen Lift annotation -->
            <line x1="160" y1="390" x2="280" y2="390" class="grid-line" stroke-dasharray="4" />
            <path d="M220,390 L220,330" stroke="var(--text-muted)" stroke-width="1" marker-end="url(#arrow)" />
            <text x="210" y="360" class="blueprint-text" text-anchor="end">抬升 100mm</text>
            
            <!-- Float action annotation -->
            <path d="M420,430 L380,430 L380,396" stroke="var(--text-muted)" stroke-width="1" fill="none" />
            <text x="430" y="434" class="blueprint-text">液位行程 250mm</text>
            
            <!-- Mechanical Ratio -->
            <text x="430" y="280" class="blueprint-text">放大比 1:2</text>
            <text x="880" y="660" class="blueprint-text">放大比联动</text>
        </g>

        <defs>
            <marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--text-muted)" />
            </marker>
        </defs>
    </svg>

    <script>
        /**
         * Animation Math & Logic
         * Driven by a 0-100 master timeline loop
         */
        const state = {
            t: 0,
            playing: true,
            speed: 0.15
        };

        // DOM Elements
        const els = {
            inlet_fluid: document.getElementById('inlet-fluid'),
            weir_plate: document.getElementById('weir-plate'),
            screen_group: document.getElementById('screen-group'),
            screen_liquid: document.getElementById('screen-liquid'),
            float1: document.getElementById('float1'),
            lever1: document.getElementById('lever1'),
            air_line_in: document.getElementById('air-line-in'),
            air_line_out: document.getElementById('air-line-out'),
            cylinder_rod: document.getElementById('cylinder-rod'),
            cylinder_pin: document.getElementById('cylinder-pin'),
            wire_rope: document.getElementById('wire-rope'),
            dump_fluid: document.getElementById('dump-fluid'),
            tank_liquid: document.getElementById('tank-liquid'),
            float2: document.getElementById('float2'),
            lever2: document.getElementById('lever2'),
            valve_disc: document.getElementById('valve-disc'),
            drain_fluid: document.getElementById('drain-fluid'),
            timeline: document.getElementById('timeline'),
            phase_label: document.getElementById('phase-label'),
            play_btn: document.getElementById('playBtn'),
            icon_play: document.getElementById('icon-play'),
            icon_pause: document.getElementById('icon-pause')
        };

        // Easing functions for mechanical realism
        function easeInOutQuad(x) {
            return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
        }

        // Map a time segment to a 0-1 value
        function mapTime(t, start, end) {
            if (t <= start) return 0;
            if (t >= end) return 1;
            return easeInOutQuad((t - start) / (end - start));
        }

        function updateFrame() {
            let t = state.t; // 0 to 100

            // 1. Inflow fills screen (0-20), then drains (40-60)
            let L1_fill = mapTime(t, 0, 20);
            let L1_drain = mapTime(t, 40, 60);
            let L1 = L1_fill - L1_drain; // 0.0 to 1.0

            // 2. Float 1 directly follows L1 mechanically
            let F1 = L1;

            // 3. Pneumatic Valve triggers when F1 > 0.8. 
            // Cylinder actuates (20-35), drops (75-90)
            let airOn = (t > 18 && t < 78);
            let C1_up = mapTime(t, 20, 35);
            let C1_down = mapTime(t, 75, 90);
            let C1 = C1_up - C1_down; // 0.0 to 1.0

            // 4. Fluid flow from screen to tank happens when screen is lifted
            let dump_active = (t > 38 && t < 65);
            
            // 5. Tank fills (40-65), drains (65-85)
            let L2_fill = mapTime(t, 40, 65);
            let L2_drain = mapTime(t, 65, 85);
            let L2 = L2_fill - L2_drain; // 0.0 to 1.0

            // 6. Tank Float directly follows L2
            let F2 = L2;

            // 7. Valve Disc linked to F2
            let V1 = F2;

            // --- DOM UPDATES ---

            // Screen Liquid Height (Max 65px)
            let liquidH = L1 * 65;
            els.screen_liquid.setAttribute('y', 380 - liquidH);
            els.screen_liquid.setAttribute('height', liquidH);

            // Screen Float 1 (Moves up with liquid)
            let f1_y = 364 - liquidH;
            els.float1.setAttribute('cy', f1_y);
            
            // Lever 1 Rotation based on F1
            let lever1_angle = -F1 * 25; // max 25 deg up
            els.lever1.setAttribute('transform', `rotate(${lever1_angle}, 430, 300)`);

            // Air Logic
            if (airOn) {
                els.air_line_in.classList.add('active');
                els.air_line_out.classList.add('active');
            } else {
                els.air_line_in.classList.remove('active');
                els.air_line_out.classList.remove('active');
            }

            // Cylinder Extends (Max 60px)
            let cyl_ext = C1 * 60;
            els.cylinder_rod.setAttribute('y', 380 - cyl_ext);
            els.cylinder_rod.setAttribute('height', 100 + cyl_ext);
            els.cylinder_pin.setAttribute('cy', 380 - cyl_ext);

            // Screen Box Tilt (Max 12 deg)
            let screen_angle = C1 * 12;
            els.screen_group.setAttribute('transform', `rotate(${-screen_angle}, 720, 390)`);

            // Weir Plate & Wire Rope (closes 50% = drops 45px)
            let weir_drop = C1 * 45;
            els.weir_plate.setAttribute('transform', `translate(0, ${weir_drop})`);
            
            // Adjust Inlet fluid visual based on weir
            if (weir_drop > 0) {
                els.inlet_fluid.setAttribute('d', `M230,${180+weir_drop} L270,${180+weir_drop} L270,320 L230,320 Z`);
            } else {
                els.inlet_fluid.setAttribute('d', `M230,180 L270,180 L270,320 L230,320 Z`);
            }

            // Dynamic Wire Rope Path
            els.wire_rope.setAttribute('d', `M310,${380 - cyl_ext} L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,${100 + weir_drop}`);

            // Dump Fluid Appearance
            els.dump_fluid.setAttribute('opacity', dump_active ? (C1 * 0.9) : 0);

            // Tank Liquid Height (Max 150px)
            let tank_liquidH = L2 * 150;
            els.tank_liquid.setAttribute('y', 750 - tank_liquidH);
            els.tank_liquid.setAttribute('height', tank_liquidH);

            // Tank Float 2
            let f2_y = 730 - tank_liquidH;
            els.float2.setAttribute('cy', f2_y);

            // Lever 2 Rotation (Pivot 950, 682)
            let lever2_angle = -F2 * 35; 
            els.lever2.setAttribute('transform', `rotate(${lever2_angle}, 950, 682)`);
            els.lever2.setAttribute('y1', f2_y);

            // Butterfly Valve Disc Rotation (0 to 90deg)
            let valve_angle = V1 * 90;
            els.valve_disc.setAttribute('transform', `rotate(${valve_angle}, 1040, 720)`);

            // Drain Fluid Appearance
            els.drain_fluid.setAttribute('opacity', V1 > 0.1 ? V1 : 0);

            // UI Updates
            if (state.playing) {
                els.timeline.value = t;
                els.phase_label.innerText = Math.floor(t) + '%';
            }
        }

        function loop() {
            if (state.playing) {
                state.t += state.speed;
                if (state.t > 100) state.t = 0;
                updateFrame();
            }
            requestAnimationFrame(loop);
        }

        // Interactivity
        els.timeline.addEventListener('input', (e) => {
            state.t = parseFloat(e.target.value);
            els.phase_label.innerText = Math.floor(state.t) + '%';
            updateFrame();
        });

        els.timeline.addEventListener('mousedown', () => { state.playing = false; updatePlayBtn(); });
        els.timeline.addEventListener('mouseup', () => { state.playing = true; updatePlayBtn(); });

        els.play_btn.addEventListener('click', () => {
            state.playing = !state.playing;
            updatePlayBtn();
        });

        function updatePlayBtn() {
            if(state.playing) {
                els.icon_pause.style.display = 'block';
                els.icon_play.style.display = 'none';
            } else {
                els.icon_pause.style.display = 'none';
                els.icon_play.style.display = 'block';
            }
        }

        // Auto-start on load
        window.addEventListener('DOMContentLoaded', () => {
            state.t = 0;
            state.playing = true;
            updatePlayBtn();
            loop();
        });

    </script>
</body>
</html>
积分规则:每轮对话扣10分