分享图
动画工坊
引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高膨胀推杆正锁合结构原理演示 - TRIZ IFR</title>
    <style>
        :root {
            --bg-color: #050914;
            --grid-color: rgba(30, 41, 59, 0.5);
            --text-main: #94A3B8;
            --text-highlight: #38BDF8;
            --text-alert: #F87171;
            --part-fixed: #0F172A;
            --part-stroke: #334155;
            --accent-cold: #3B82F6;
            --accent-hot: #EF4444;
            --block-color: #F59E0B;
        }

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

        body {
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: 'JetBrains Mono', 'Courier New', Consolas, monospace;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            overflow: hidden;
        }

        .canvas-container {
            width: 100vw;
            height: 100vh;
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1400px;
            max-height: 900px;
            filter: drop-shadow(0 0 20px rgba(0, 0, 0, 0.5));
        }

        text {
            user-select: none;
        }

        .hud-title {
            font-size: 16px;
            font-weight: bold;
            fill: #F8FAFC;
            letter-spacing: 1px;
        }

        .hud-text {
            font-size: 12px;
            fill: #94A3B8;
        }

        .hud-value {
            font-size: 13px;
            font-weight: bold;
            fill: var(--text-highlight);
            font-variant-numeric: tabular-nums;
        }

        .hud-panel {
            fill: rgba(15, 23, 42, 0.8);
            stroke: var(--part-stroke);
            stroke-width: 1;
            rx: 6;
        }
        
        .axis-line {
            stroke: rgba(148, 163, 184, 0.2);
            stroke-dasharray: 4 4;
            stroke-width: 1;
        }
    </style>
</head>
<body>

<div class="canvas-container">
    <svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet" id="mainSvg">
        <!-- Definitions -->
        <defs>
            <!-- Blueprint Grid -->
            <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                <path d="M 40 0 L 0 0 0 40" fill="none" stroke="var(--grid-color)" stroke-width="0.5"/>
            </pattern>
            
            <!-- Mechanical Hatching for Fixed Parts -->
            <pattern id="hatch" width="10" height="10" patternUnits="userSpaceOnUse">
                <rect width="10" height="10" fill="var(--part-fixed)" />
                <path d="M-2,12 L12,-2" stroke="#1E293B" stroke-width="1.5" />
            </pattern>
            
            <!-- Inner Guide Fill -->
            <pattern id="hatch-guide" width="8" height="8" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
                <rect width="8" height="8" fill="#172033" />
                <line x1="0" y1="0" x2="0" y2="8" stroke="#28354D" stroke-width="1" />
            </pattern>

            <!-- Glow Filters -->
            <filter id="glow-hot" x="-20%" y="-20%" width="140%" height="140%">
                <feGaussianBlur stdDeviation="8" result="blur" />
                <feComposite in="SourceGraphic" in2="blur" operator="over" />
            </filter>

            <!-- Gradients -->
            <linearGradient id="rod-grad-cold" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" stop-color="#1E293B" />
                <stop offset="20%" stop-color="#475569" />
                <stop offset="50%" stop-color="#94A3B8" />
                <stop offset="80%" stop-color="#475569" />
                <stop offset="100%" stop-color="#1E293B" />
            </linearGradient>

            <linearGradient id="rod-grad-hot" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" stop-color="#7F1D1D" />
                <stop offset="20%" stop-color="#B91C1C" />
                <stop offset="50%" stop-color="#FCA5A5" />
                <stop offset="80%" stop-color="#B91C1C" />
                <stop offset="100%" stop-color="#7F1D1D" />
            </linearGradient>

            <linearGradient id="block-grad" x1="0%" y1="0%" x2="0%" y2="100%">
                <stop offset="0%" stop-color="#F59E0B" />
                <stop offset="50%" stop-color="#FCD34D" />
                <stop offset="100%" stop-color="#D97706" />
            </linearGradient>
        </defs>

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

        <!-- Centerline -->
        <line x1="500" y1="50" x2="500" y2="650" stroke="#64748B" stroke-dasharray="15 5 5 5" stroke-width="1" opacity="0.5" />
        <line x1="150" y1="510" x2="850" y2="510" stroke="#64748B" stroke-dasharray="15 5 5 5" stroke-width="1" opacity="0.3" />

        <!-- ================= MECHANISM ================= -->
        <g id="mechanismGroup">
            
            <!-- 1. FIXED OUTER SUPPORTS (支座) -->
            <!-- Left Fixed Support -->
            <path d="M 150,100 L 340,100 L 340,485 L 300,485 L 300,535 L 340,535 L 340,650 L 150,650 Z" 
                  fill="url(#hatch)" stroke="var(--accent-cold)" stroke-width="1.5" />
            <!-- Right Fixed Support -->
            <path d="M 850,100 L 660,100 L 660,485 L 700,485 L 700,535 L 660,535 L 660,650 L 850,650 Z" 
                  fill="url(#hatch)" stroke="var(--accent-cold)" stroke-width="1.5" />

            <!-- 2. INNER GUIDES (导向槽法兰) -->
            <!-- Left Top Guide -->
            <path d="M 340,100 L 435,100 L 435,485 L 340,485 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
            <!-- Left Bottom Guide -->
            <path d="M 340,550 L 435,550 L 435,650 L 340,650 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
            
            <!-- Right Top Guide -->
            <path d="M 660,100 L 565,100 L 565,485 L 660,485 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
            <!-- Right Bottom Guide -->
            <path d="M 660,550 L 565,550 L 565,650 L 660,650 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />

            <!-- 3. PUSH ROD (高膨胀推杆 - Moves Vertically) -->
            <g id="pushRod" transform="translate(0, 0)">
                <!-- Cold State Body -->
                <rect x="440" y="0" width="120" height="600" fill="url(#rod-grad-cold)" stroke="#64748B" stroke-width="1.5" id="rodBodyCold"/>
                <!-- Hot State Body (Opacity controlled by JS) -->
                <rect x="440" y="0" width="120" height="600" fill="url(#rod-grad-hot)" stroke="#FCA5A5" stroke-width="2" id="rodBodyHot" opacity="0" filter="url(#glow-hot)"/>
                
                <!-- Left Slanted Slot (Cutout illusion) -->
                <!-- Slot trajectory: x1=440, y1=480 to x2=500, y2=540 -->
                <path d="M 438,478 L 442,478 L 502,538 L 498,538 Z" fill="#020617" opacity="0.8" />
                <line x1="440" y1="480" x2="500" y2="540" stroke="#0B101E" stroke-width="14" stroke-linecap="round" />
                <line x1="440" y1="480" x2="500" y2="540" stroke="#1E293B" stroke-width="12" stroke-linecap="round" />
                
                <!-- Right Slanted Slot -->
                <path d="M 562,478 L 558,478 L 498,538 L 502,538 Z" fill="#020617" opacity="0.8" />
                <line x1="560" y1="480" x2="500" y2="540" stroke="#0B101E" stroke-width="14" stroke-linecap="round" />
                <line x1="560" y1="480" x2="500" y2="540" stroke="#1E293B" stroke-width="12" stroke-linecap="round" />

                <!-- 12° Angle Annotation -->
                <g stroke="#94A3B8" stroke-width="1" fill="none" opacity="0.8">
                    <line x1="440" y1="480" x2="440" y2="540" stroke-dasharray="2 2" />
                    <path d="M 440,510 A 30 30 0 0 0 470,510" stroke-dasharray="2 2"/>
                    <text x="445" y="525" class="hud-text" fill="#94A3B8" stroke="none">12°</text>
                </g>
            </g>

            <!-- 4. SPRINGS (回位弹簧 - Paths updated by JS) -->
            <path id="springLeft" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linejoin="round" />
            <path id="springRight" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linejoin="round" />

            <!-- 5. LOCK BLOCKS (径向锁块 - Moves Horizontally) -->
            <!-- Left Block Group -->
            <g id="blockLeft" transform="translate(0, 0)">
                <!-- Main Block -->
                <path d="M 370,485 L 470,485 L 470,535 L 370,535 Z" fill="url(#block-grad)" stroke="#B45309" stroke-width="1.5" />
                <!-- Spring Anchor Tab -->
                <path d="M 400,535 L 420,535 L 420,550 L 400,550 Z" fill="#92400E" stroke="#78350F" stroke-width="1" />
                <circle cx="410" cy="542.5" r="2.5" fill="#CBD5E1" />
                <!-- Drive Pin (Roller) -->
                <circle cx="470" cy="510" r="7" fill="#E2E8F0" stroke="#475569" stroke-width="2" />
                <circle cx="470" cy="510" r="3" fill="#64748B" />
                <!-- Motion Indicator Arrows -->
                <path id="arrowLeft" d="M 350,510 L 360,505 L 360,515 Z" fill="#F87171" opacity="0" />
            </g>

            <!-- Right Block Group -->
            <g id="blockRight" transform="translate(0, 0)">
                <!-- Main Block -->
                <path d="M 630,485 L 530,485 L 530,535 L 630,535 Z" fill="url(#block-grad)" stroke="#B45309" stroke-width="1.5" />
                <!-- Spring Anchor Tab -->
                <path d="M 600,535 L 580,535 L 580,550 L 600,550 Z" fill="#92400E" stroke="#78350F" stroke-width="1" />
                <circle cx="590" cy="542.5" r="2.5" fill="#CBD5E1" />
                <!-- Drive Pin (Roller) -->
                <circle cx="530" cy="510" r="7" fill="#E2E8F0" stroke="#475569" stroke-width="2" />
                <circle cx="530" cy="510" r="3" fill="#64748B" />
                <!-- Motion Indicator Arrows -->
                <path id="arrowRight" d="M 650,510 L 640,505 L 640,515 Z" fill="#F87171" opacity="0" />
            </g>

            <!-- Fixed Spring Anchors on Guide -->
            <path d="M 430,535 L 440,535 L 440,550 L 430,550 Z" fill="#1E293B" stroke="#0F172A" />
            <circle cx="435" cy="542.5" r="2.5" fill="#64748B" />
            
            <path d="M 570,535 L 560,535 L 560,550 L 570,550 Z" fill="#1E293B" stroke="#0F172A" />
            <circle cx="565" cy="542.5" r="2.5" fill="#64748B" />

        </g>

        <!-- ================= HUD & ANNOTATIONS ================= -->
        
        <!-- Top Left Status HUD -->
        <g transform="translate(30, 30)">
            <rect width="240" height="130" class="hud-panel" />
            <text x="15" y="25" class="hud-title">SYSTEM STATUS</text>
            <line x1="15" y1="35" x2="225" y2="35" stroke="var(--part-stroke)" stroke-width="1" />
            
            <text x="15" y="55" class="hud-text">系统温度 (TEMP):</text>
            <text x="160" y="55" class="hud-value" id="valTemp">150.0 ℃</text>
            
            <text x="15" y="75" class="hud-text">推杆轴向位移 (ΔY):</text>
            <text x="160" y="75" class="hud-value" id="valRodY">0.00 mm</text>
            
            <text x="15" y="95" class="hud-text">锁块径向伸出 (ΔX):</text>
            <text x="160" y="95" class="hud-value" id="valBlockX">0.00 mm</text>

            <text x="15" y="115" class="hud-text">锁合状态 (LOCK):</text>
            <text x="160" y="115" class="hud-value" id="valStatus" fill="#34D399">UNLOCKED</text>
        </g>

        <!-- Top Right TRIZ IFR HUD -->
        <g transform="translate(680, 30)">
            <rect width="290" height="110" class="hud-panel" />
            <text x="15" y="25" class="hud-title" fill="#FBBF24">TRIZ 最终理想解 (IFR)</text>
            <line x1="15" y1="35" x2="275" y2="35" stroke="var(--part-stroke)" stroke-width="1" />
            
            <text x="15" y="55" class="hud-text" fill="#E2E8F0">核心矛盾消除:承载力 vs 系统复杂度</text>
            <text x="15" y="75" class="hud-text">利用系统固有的<tspan fill="#FCA5A5">【温差热能】</tspan>作为驱动源</text>
            <text x="15" y="95" class="hud-text">无须外部动力,实现绝对可靠的自动正锁合</text>
        </g>

        <!-- Mechanism Labels (Static) -->
        <g class="hud-text">
            <!-- Rod Label -->
            <line x1="500" y1="200" x2="600" y2="150" stroke="#94A3B8" stroke-width="1" />
            <text x="605" y="148">高膨胀镍基合金推杆</text>
            <text x="605" y="163" font-size="10" fill="#64748B">CTE ≈ 17×10⁻⁶/℃</text>

            <!-- Annular Groove Label -->
            <line x1="300" y1="510" x2="210" y2="450" stroke="#94A3B8" stroke-width="1" />
            <text x="120" y="445">固定支座环形锁槽</text>
            
            <!-- Lock Block Label -->
            <line x1="390" y1="490" x2="310" y2="410" stroke="#94A3B8" stroke-width="1" />
            <text x="260" y="405">径向正锁合锁块</text>
            
            <!-- Spring Label -->
            <line x1="430" y1="550" x2="350" y2="590" stroke="#94A3B8" stroke-width="1" />
            <text x="300" y="605">强力回位弹簧</text>

            <!-- Slope Extender Label -->
            <line x1="520" y1="510" x2="600" y2="570" stroke="#94A3B8" stroke-width="1" />
            <text x="605" y="575">12° 斜槽 (运动行程放大)</text>
        </g>
    </svg>
</div>

<script>
    // Elements
    const rodCold = document.getElementById('rodBodyCold');
    const rodHot = document.getElementById('rodBodyHot');
    const pushRod = document.getElementById('pushRod');
    const blockLeft = document.getElementById('blockLeft');
    const blockRight = document.getElementById('blockRight');
    const springLeft = document.getElementById('springLeft');
    const springRight = document.getElementById('springRight');
    const arrowLeft = document.getElementById('arrowLeft');
    const arrowRight = document.getElementById('arrowRight');
    
    // HUD Elements
    const valTemp = document.getElementById('valTemp');
    const valRodY = document.getElementById('valRodY');
    const valBlockX = document.getElementById('valBlockX');
    const valStatus = document.getElementById('valStatus');

    // Animation Constants
    const CYCLE_DURATION = 12000; // Total ms per cycle
    const MAX_ROD_Y = 60; // visual px
    const MAX_BLOCK_X = 60; // visual px
    const MAX_TEMP = 300;
    const MIN_TEMP = 150;
    
    // Physics / Engineering mapped constants for HUD
    const REAL_MAX_ROD_MM = 0.77;
    const REAL_MAX_BLOCK_MM = 3.60;

    // Easing function (Smooth sine wave style acceleration/deceleration)
    function easeInOutCubic(x) {
        return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
    }

    // Spring Drawing Generator (Draws a realistic zigzag spring)
    function drawSpringPath(x1, x2, y, coils, amplitude) {
        let path = `M ${x1},${y} `;
        const dir = x2 > x1 ? 1 : -1;
        const totalW = Math.abs(x2 - x1);
        const startPad = 5;
        
        path += `L ${x1 + dir * startPad},${y} `;
        
        const workingW = totalW - startPad * 2;
        const step = workingW / coils;
        
        let currentX = x1 + dir * startPad;
        
        for (let i = 0; i < coils; i++) {
            path += `L ${currentX + dir * (step * 0.25)},${y - amplitude} `;
            path += `L ${currentX + dir * (step * 0.75)},${y + amplitude} `;
            path += `L ${currentX + dir * step},${y} `;
            currentX += dir * step;
        }
        
        path += `L ${x2},${y}`;
        return path;
    }

    // Main animation loop
    function animate(timestamp) {
        const timeInCycle = timestamp % CYCLE_DURATION;
        let progress = 0; // 0 to 1

        // Define cycle phases
        // 0-15%: Idle Cool (150)
        // 15-40%: Heating up
        // 40-65%: Hold Hot (300) -> Locked State
        // 65-90%: Cooling down
        // 90-100%: Idle Cool (150)

        const pHeatStart = 0.15, pHeatEnd = 0.40;
        const pCoolStart = 0.65, pCoolEnd = 0.90;
        const normTime = timeInCycle / CYCLE_DURATION;

        if (normTime < pHeatStart) {
            progress = 0;
        } else if (normTime < pHeatEnd) {
            const t = (normTime - pHeatStart) / (pHeatEnd - pHeatStart);
            progress = easeInOutCubic(t);
        } else if (normTime < pCoolStart) {
            progress = 1;
        } else if (normTime < pCoolEnd) {
            const t = (normTime - pCoolStart) / (pCoolEnd - pCoolStart);
            progress = 1 - easeInOutCubic(t);
        } else {
            progress = 0;
        }

        // 1. Update Transforms
        const currentRodY = MAX_ROD_Y * progress;
        const currentBlockX = MAX_BLOCK_X * progress;

        pushRod.setAttribute('transform', `translate(0, ${currentRodY})`);
        blockLeft.setAttribute('transform', `translate(${-currentBlockX}, 0)`);
        blockRight.setAttribute('transform', `translate(${currentBlockX}, 0)`);

        // 2. Update Springs
        // Left Spring: fixed anchor at x=435, tab moves from 410 down to 350
        const leftTabX = 410 - currentBlockX;
        springLeft.setAttribute('d', drawSpringPath(435, leftTabX, 542.5, 6, 4));
        
        // Right Spring: fixed anchor at x=565, tab moves from 590 up to 650
        const rightTabX = 590 + currentBlockX;
        springRight.setAttribute('d', drawSpringPath(565, rightTabX, 542.5, 6, 4));

        // 3. Visual FX (Heat Glow)
        rodHot.setAttribute('opacity', progress.toFixed(2));
        
        // Motion arrows
        const isMovingOut = normTime > pHeatStart && normTime < pHeatEnd;
        arrowLeft.setAttribute('opacity', isMovingOut ? '1' : '0');
        arrowRight.setAttribute('opacity', isMovingOut ? '1' : '0');

        // 4. Update HUD Data
        const currentTemp = MIN_TEMP + (MAX_TEMP - MIN_TEMP) * progress;
        valTemp.textContent = `${currentTemp.toFixed(1)} ℃`;
        
        // Color mapping for temperature text
        if (progress > 0.8) valTemp.setAttribute('fill', '#FCA5A5');
        else if (progress > 0.3) valTemp.setAttribute('fill', '#FCD34D');
        else valTemp.setAttribute('fill', '#38BDF8');

        valRodY.textContent = `${(REAL_MAX_ROD_MM * progress).toFixed(2)} mm`;
        valBlockX.textContent = `${(REAL_MAX_BLOCK_MM * progress).toFixed(2)} mm`;

        if (progress > 0.95) {
            valStatus.textContent = "正锁合 (LOCKED)";
            valStatus.setAttribute('fill', '#EF4444');
        } else if (progress < 0.05) {
            valStatus.textContent = "释放 (UNLOCKED)";
            valStatus.setAttribute('fill', '#34D399');
        } else {
            valStatus.textContent = "动作中 (TRANSITION)";
            valStatus.setAttribute('fill', '#FBBF24');
        }

        requestAnimationFrame(animate);
    }

    // Start animation loop immediately
    requestAnimationFrame(animate);
</script>

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