分享图
动画工坊
引擎就绪
<!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>
        @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;500;700&display=swap');

        :root {
            --bg-color: #0B0E14;
            --grid-color: rgba(255, 255, 255, 0.03);
            --fluid-color: #00D8FF;
            --fluid-glow: rgba(0, 216, 255, 0.4);
            --metal-light: #E2E8F0;
            --metal-dark: #64748B;
            --accent-color: #FF5500;
            --text-color: #8B9BB4;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            font-family: 'JetBrains Mono', monospace;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* Blueprint Grid Background */
        .bg-grid {
            position: absolute;
            top: 0; left: 0; width: 100%; height: 100%;
            background-image: 
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 40px 40px;
            z-index: 0;
        }

        .bg-grid::after {
            content: '';
            position: absolute;
            top: 0; left: 0; width: 100%; height: 100%;
            background: radial-gradient(circle at center, transparent 30%, var(--bg-color) 100%);
        }

        /* SVG Container */
        .svg-container {
            position: relative;
            width: 100%;
            max-width: 1200px;
            height: 100vh;
            z-index: 10;
        }

        svg {
            width: 100%;
            height: 100%;
            display: block;
        }

        /* Typography & Overlays - Strictly minimized and pushed to edges */
        .overlay {
            position: absolute;
            z-index: 20;
            pointer-events: none;
            color: var(--text-color);
            font-size: 12px;
            letter-spacing: 1px;
            line-height: 1.6;
        }

        .overlay-top-left { top: 32px; left: 40px; }
        .overlay-bottom-left { bottom: 32px; left: 40px; }
        .overlay-bottom-right { bottom: 32px; right: 40px; text-align: right; }

        .title {
            color: var(--metal-light);
            font-size: 16px;
            font-weight: 700;
            margin-bottom: 8px;
            text-transform: uppercase;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .title::before {
            content: '';
            display: inline-block;
            width: 8px;
            height: 8px;
            background-color: var(--accent-color);
            box-shadow: 0 0 8px var(--accent-color);
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            width: 220px;
            border-bottom: 1px solid rgba(139, 155, 180, 0.1);
            padding: 4px 0;
        }

        .data-value {
            color: var(--fluid-color);
            font-weight: 500;
        }

        .accent-text { color: var(--accent-color); }

        /* Flow Animation CSS */
        .flow-dash {
            stroke-dasharray: 10 10;
            animation: flow 0.5s linear infinite;
        }

        @keyframes flow {
            to { stroke-dashoffset: -20; }
        }

        .glow { filter: drop-shadow(0 0 12px var(--fluid-glow)); }
        .metal-glow { filter: drop-shadow(0 4px 6px rgba(0,0,0,0.5)); }
    </style>
</head>
<body>

    <div class="bg-grid"></div>

    <!-- Data Overlays -->
    <div class="overlay overlay-top-left">
        <div class="title">IFR: 最终理想解</div>
        <div style="margin-bottom: 16px; color: #5a6b85;">完全利用系统内部资源(重力、浮力)<br>实现负反馈调控,消除外部能源依赖。</div>
        <div class="data-row"><span>当前液位高度</span><span class="data-value" id="ui-level">0 mm</span></div>
        <div class="data-row"><span>浮球升降行程</span><span class="data-value" id="ui-stroke">0 mm</span></div>
        <div class="data-row"><span>作用力臂比</span><span class="data-value accent-text">1:3</span></div>
        <div class="data-row"><span>蝶阀开度状态</span><span class="data-value" id="ui-valve">0.0°</span></div>
        <div class="data-row"><span>系统能耗</span><span class="data-value" style="color: #00FF66;">0.00 kW</span></div>
    </div>

    <div class="overlay overlay-bottom-left">
        <span class="accent-text">SYS.STAT //</span> 纯机械自适应稳态运行中
    </div>

    <div class="overlay overlay-bottom-right">
        核心机理: 负反馈杠杆机构<br>
        适用边界: 缓冲罐液位缓变场景
    </div>

    <!-- Main SVG Animation -->
    <div class="svg-container">
        <svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet">
            <defs>
                <linearGradient id="metalGrad" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="#E2E8F0" />
                    <stop offset="50%" stop-color="#94A3B8" />
                    <stop offset="100%" stop-color="#475569" />
                </linearGradient>
                <linearGradient id="fluidGrad" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="rgba(0, 216, 255, 0.8)" />
                    <stop offset="100%" stop-color="rgba(0, 85, 119, 0.9)" />
                </linearGradient>
                <linearGradient id="darkMetal" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="#475569" />
                    <stop offset="100%" stop-color="#1E293B" />
                </linearGradient>
                <filter id="neonGlow" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
            </defs>

            <!-- 1. Background Structure (Tank & Pipes) -->
            <g id="tank-structure">
                <!-- Inflow pipe -->
                <path d="M 220 0 L 220 80" fill="none" stroke="var(--metal-dark)" stroke-width="16" />
                <path d="M 220 0 L 220 80" fill="none" stroke="var(--bg-color)" stroke-width="12" />
                <path d="M 220 0 L 220 100" fill="none" stroke="var(--fluid-color)" stroke-width="6" class="flow-dash glow" opacity="0.5" />

                <!-- Main Tank -->
                <rect x="150" y="100" width="200" height="350" fill="rgba(30, 41, 59, 0.4)" stroke="var(--metal-dark)" stroke-width="4" rx="8" />
                
                <!-- Outflow Pipe -->
                <path d="M 350 410 L 800 410" fill="none" stroke="var(--metal-dark)" stroke-width="32" stroke-linecap="round"/>
                <path d="M 350 410 L 800 410" fill="none" stroke="var(--bg-color)" stroke-width="26" stroke-linecap="round"/>
            </g>

            <!-- 2. Dynamic Fluid -->
            <g id="fluid-group">
                <!-- Tank Fluid -->
                <rect id="tank-fluid" x="152" y="300" width="196" height="148" fill="url(#fluidGrad)" class="glow" rx="6" />
                <line id="fluid-surface" x1="152" y1="300" x2="348" y2="300" stroke="#FFFFFF" stroke-width="2" opacity="0.5" />

                <!-- Outflow Fluid (Masked to pipe) -->
                <clipPath id="pipe-clip">
                    <rect x="350" y="396" width="450" height="28" />
                </clipPath>
                <g clip-path="url(#pipe-clip)">
                    <rect id="outflow-fluid" x="350" y="396" width="450" height="28" fill="var(--fluid-color)" opacity="0" class="glow" />
                    <line id="outflow-dash" x1="350" y1="410" x2="800" y2="410" stroke="#FFFFFF" stroke-width="4" opacity="0" class="flow-dash" />
                </g>
            </g>

            <!-- 3. Mechanical System (IFR Core) -->
            <g id="mechanism" class="metal-glow">
                
                <!-- Support Bracket -->
                <path d="M 540 100 L 560 100 L 560 220 L 540 220 Z" fill="url(#darkMetal)" />
                <circle cx="550" cy="200" r="12" fill="url(#metalGrad)" />
                <circle cx="550" cy="200" r="4" fill="var(--bg-color)" />

                <!-- Float Ball -->
                <g id="float-assembly">
                    <rect x="245" y="0" width="10" height="100" fill="url(#metalGrad)" id="float-rod" />
                    <!-- Stainless Steel Float -->
                    <ellipse cx="250" cy="0" rx="40" ry="30" fill="url(#metalGrad)" id="float-ball" />
                    <ellipse cx="250" cy="-15" rx="20" ry="8" fill="#FFFFFF" opacity="0.3" id="float-highlight" />
                </g>

                <!-- Main Lever (Force Arm & Resistance Arm 3:1) -->
                <!-- Pivot is at 550, 200. Float attaches at 250 (Distance 300). Linkage at 650 (Distance 100). -->
                <g id="main-lever">
                    <!-- The rod -->
                    <line x1="250" y1="200" x2="650" y2="200" stroke="url(#metalGrad)" stroke-width="14" stroke-linecap="round" id="lever-arm" />
                    <!-- Pivot Joint -->
                    <circle cx="550" cy="200" r="8" fill="var(--accent-color)" filter="url(#neonGlow)" />
                    <!-- Force Vector Indications -->
                    <text x="400" y="185" fill="var(--accent-color)" font-size="12" text-anchor="middle" opacity="0.8">L1 = 3x (浮力臂)</text>
                    <text x="600" y="185" fill="var(--accent-color)" font-size="12" text-anchor="middle" opacity="0.8">L2 = 1x</text>
                </g>

                <!-- Vertical Linkage Rod -->
                <g id="linkage-assembly">
                    <line x1="650" y1="200" x2="650" y2="350" stroke="url(#metalGrad)" stroke-width="8" stroke-linecap="round" id="linkage-rod" />
                    <circle cx="650" cy="200" r="6" fill="#1E293B" stroke="url(#metalGrad)" stroke-width="2" id="joint-top" />
                    <circle cx="650" cy="350" r="6" fill="#1E293B" stroke="url(#metalGrad)" stroke-width="2" id="joint-bottom" />
                </g>

                <!-- Butterfly Valve Assembly -->
                <g id="valve-assembly">
                    <!-- Valve Body Exterior -->
                    <rect x="620" y="380" width="60" height="60" fill="url(#darkMetal)" rx="4" />
                    <line x1="650" y1="370" x2="650" y2="380" stroke="url(#metalGrad)" stroke-width="6" />
                    
                    <!-- Valve Lever (connects linkage to valve axis) -->
                    <line x1="650" y1="350" x2="650" y2="410" stroke="var(--metal-light)" stroke-width="10" stroke-linecap="round" id="valve-lever" />
                    <circle cx="650" cy="410" r="10" fill="var(--accent-color)" filter="url(#neonGlow)" />
                    
                    <!-- Internal Valve Disc (Visible through "cutaway" or conceptual view) -->
                    <!-- Conceptual cross-section view of the pipe at the valve -->
                    <ellipse cx="650" cy="410" rx="12" ry="24" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="2" />
                    <line x1="650" y1="386" x2="650" y2="434" stroke="#FFF" stroke-width="6" id="valve-disc" stroke-linecap="round" />
                </g>
                
                <!-- Measurement Markers -->
                <g opacity="0.4" font-size="10" fill="var(--text-color)">
                    <!-- Stroke indicator -->
                    <line x1="100" y1="210" x2="140" y2="210" stroke="var(--text-color)" stroke-width="1" stroke-dasharray="2 2" />
                    <line x1="100" y1="310" x2="140" y2="310" stroke="var(--text-color)" stroke-width="1" stroke-dasharray="2 2" />
                    <path d="M 120 210 L 120 310" fill="none" stroke="var(--text-color)" stroke-width="1" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
                    <text x="110" y="265" text-anchor="end" transform="rotate(-90, 110, 265)">100mm 行程</text>
                </g>

            </g>

            <!-- Markers definition -->
            <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="var(--text-color)" />
                </marker>
            </defs>

        </svg>
    </div>

    <script>
        /**
         * Core Logic: Procedural animation based on sine wave to simulate continuous 
         * operation of the IFR mechanical feedback loop. 
         * No user interaction required, auto-starts on load.
         */
        document.addEventListener('DOMContentLoaded', () => {
            // DOM Elements
            const els = {
                tankFluid: document.getElementById('tank-fluid'),
                fluidSurface: document.getElementById('fluid-surface'),
                floatAssembly: document.getElementById('float-assembly'),
                floatRod: document.getElementById('float-rod'),
                mainLever: document.getElementById('main-lever'),
                linkageRod: document.getElementById('linkage-rod'),
                jointTop: document.getElementById('joint-top'),
                jointBottom: document.getElementById('joint-bottom'),
                valveLever: document.getElementById('valve-lever'),
                valveDisc: document.getElementById('valve-disc'),
                outflowFluid: document.getElementById('outflow-fluid'),
                outflowDash: document.getElementById('outflow-dash'),
                uiLevel: document.getElementById('ui-level'),
                uiStroke: document.getElementById('ui-stroke'),
                uiValve: document.getElementById('ui-valve')
            };

            // Kinematic Constants
            const PIVOT_X = 550;
            const PIVOT_Y = 200;
            const FLOAT_X = 250;
            const LINKAGE_BASE_X = 650; // Distance ratio 300 : 100 = 3:1
            const VALVE_X = 650;
            const VALVE_Y = 410;
            
            // Operating Range
            const Y_MIN = 210; // Float highest (Valve fully open)
            const Y_MAX = 310; // Float lowest (Valve fully closed)
            const STROKE = Y_MAX - Y_MIN;
            
            // Animation state
            let startTime = performance.now();
            const CYCLE_DURATION = 12000; // ms per full up/down cycle

            function animate(currentTime) {
                // 1. Calculate normalized progress [0.0, 1.0] using smooth sine wave
                const elapsed = currentTime - startTime;
                const phase = (elapsed % CYCLE_DURATION) / CYCLE_DURATION * Math.PI * 2;
                // p = 0 (low water, closed), p = 1 (high water, open)
                const p = (Math.sin(phase - Math.PI/2) + 1) / 2;

                // 2. Compute positions
                const floatY = Y_MAX - (p * STROKE);
                
                // Calculate main lever angle
                // Angle relative to horizontal left
                const angleRad = Math.atan2(floatY - PIVOT_Y, FLOAT_X - PIVOT_X);
                const angleDeg = angleRad * (180 / Math.PI);

                // Calculate right end of lever (linkage connection)
                const leverDistRight = 100;
                const rightX = PIVOT_X + leverDistRight * Math.cos(angleRad + Math.PI);
                const rightY = PIVOT_Y + leverDistRight * Math.sin(angleRad + Math.PI);

                // Calculate valve kinematics (Stroke maps to 90 degrees)
                // When p=0 (float low), valve is closed (horizontal 0 deg)
                // When p=1 (float high), valve is open (vertical 90 deg)
                const valveAngleDeg = p * 90;
                const valveAngleRad = valveAngleDeg * (Math.PI / 180);
                
                // Valve lever geometry (length = stroke of linkage / sin(90))
                const valveLeverLength = STROKE * (100/300); // Inverse ratio
                const valveJointX = VALVE_X - valveLeverLength * Math.cos(valveAngleRad);
                const valveJointY = VALVE_Y - valveLeverLength * Math.sin(valveAngleRad);

                // 3. Apply Transforms and Attributes
                
                // Fluid Level
                els.tankFluid.setAttribute('y', floatY);
                els.tankFluid.setAttribute('height', 450 - floatY); // Tank bottom is 450
                els.fluidSurface.setAttribute('y1', floatY);
                els.fluidSurface.setAttribute('y2', floatY);

                // Float Assembly (Translate Y)
                els.floatAssembly.setAttribute('transform', `translate(0, ${floatY})`);
                
                // Float rod connects float to lever
                const rodHeight = floatY - (floatY); // Actually rod moves with float, connect point is fixed on lever
                
                // Main Lever (Rotate around pivot)
                // atan2 gives angle from positive X axis. We need rotation from horizontal.
                // Float is on left (-X). Horizontal is roughly 180 or -180.
                const rotationBaseline = Math.atan2(0, -300) * 180/Math.PI; // 180
                const currentRotation = angleDeg - rotationBaseline;
                els.mainLever.setAttribute('transform', `rotate(${currentRotation}, ${PIVOT_X}, ${PIVOT_Y})`);

                // To ensure visual perfection of linkage, we procedurally position the rod
                // between the computed endpoints rather than relying entirely on SVG transforms
                els.linkageRod.setAttribute('x1', rightX);
                els.linkageRod.setAttribute('y1', rightY);
                els.linkageRod.setAttribute('x2', valveJointX);
                els.linkageRod.setAttribute('y2', valveJointY);
                
                els.jointTop.setAttribute('cx', rightX);
                els.jointTop.setAttribute('cy', rightY);
                els.jointBottom.setAttribute('cx', valveJointX);
                els.jointBottom.setAttribute('cy', valveJointY);

                // Valve Lever
                els.valveLever.setAttribute('x1', valveJointX);
                els.valveLever.setAttribute('y1', valveJointY);
                els.valveLever.setAttribute('x2', VALVE_X);
                els.valveLever.setAttribute('y2', VALVE_Y);

                // Valve Disc (rotates 0 to 90)
                els.valveDisc.setAttribute('transform', `rotate(${valveAngleDeg}, ${VALVE_X}, ${VALVE_Y})`);

                // Outflow Fluid Dynamics (Opacity based on valve opening)
                // Add a small threshold before flow starts
                const flowOpacity = p > 0.05 ? Math.min(1, p * 1.5) : 0;
                els.outflowFluid.style.opacity = flowOpacity;
                els.outflowDash.style.opacity = flowOpacity > 0 ? 0.8 : 0;
                
                // Adjust animation speed based on flow rate
                els.outflowDash.style.animationDuration = `${1.5 - p}s`;

                // 4. Update UI Dashboard
                els.uiLevel.innerText = (p * 100).toFixed(1) + ' mm';
                els.uiStroke.innerText = (p * 100).toFixed(1) + ' mm';
                els.uiValve.innerText = valveAngleDeg.toFixed(1) + '°';

                // Loop
                requestAnimationFrame(animate);
            }

            // Start animation loop
            requestAnimationFrame(animate);
        });
    </script>
</body>
</html>
积分规则:每轮对话扣10分