分享图
动画工坊
引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TRIZ 最终理想解:轴端开花涨紧结构原理</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        :root {
            --bg-color: #0b0f19;
            --grid-color: rgba(45, 61, 94, 0.3);
            --text-main: #a3b8cc;
            --text-accent: #00f0ff;
            --accent-orange: #ff5500;
            --metal-dark: #1e2638;
            --metal-mid: #3a475e;
            --metal-light: #7b8ea8;
        }

        body {
            margin: 0;
            padding: 0;
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
        }

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

        svg {
            width: 100%;
            height: 100%;
            max-height: 800px;
            filter: drop-shadow(0 0 30px rgba(0, 240, 255, 0.05));
        }

        /* Peripheral UI Text Styling */
        .info-panel {
            position: absolute;
            background: rgba(11, 15, 25, 0.85);
            backdrop-filter: blur(8px);
            border: 1px solid rgba(0, 240, 255, 0.15);
            border-radius: 8px;
            padding: 1rem;
            pointer-events: none;
            z-index: 10;
        }

        .title-panel {
            top: 2rem;
            left: 2rem;
            border-left: 3px solid var(--text-accent);
        }

        .params-panel {
            top: 2rem;
            right: 2rem;
            text-align: right;
            border-right: 3px solid var(--accent-orange);
        }

        .desc-panel {
            bottom: 2rem;
            left: 2rem;
            max-width: 380px;
            border-bottom: 3px solid var(--metal-light);
        }

        .glow-text {
            color: var(--text-accent);
            text-shadow: 0 0 10px rgba(0, 240, 255, 0.4);
        }

        .glow-orange {
            color: var(--accent-orange);
            text-shadow: 0 0 10px rgba(255, 85, 0, 0.4);
        }

        /* Structural SVG CSS */
        .svg-metal-path {
            stroke: var(--metal-light);
            stroke-width: 1.5;
            stroke-linejoin: round;
        }
        
        .svg-hatch {
            fill: url(#hatchPattern);
        }

        .lock-indicator {
            opacity: 0;
            transition: opacity 0.1s;
        }

        .force-arrow {
            fill: var(--accent-orange);
            filter: drop-shadow(0 0 5px var(--accent-orange));
        }
    </style>
</head>
<body>

    <div class="canvas-container">
        <!-- Floating UI Overlays -->
        <div class="info-panel title-panel">
            <h1 class="text-lg font-bold text-white tracking-wider mb-1">最终理想解 (IFR) <span class="text-xs text-gray-500 ml-2">v1.0</span></h1>
            <p class="text-sm glow-text font-mono">轴端开花涨紧结构原理</p>
            <div class="mt-2 text-xs text-gray-400">
                利用系统内部资源(轴自身),无需第三方套筒,<br>突破极小空间限制,实现配合间隙自补偿。
            </div>
        </div>

        <div class="info-panel params-panel">
            <h2 class="text-sm font-bold text-white mb-2">关键工程参数</h2>
            <ul class="text-xs space-y-1 text-gray-400 font-mono">
                <li>十字槽长度: <span class="glow-orange">1.5 × D</span> (轴径)</li>
                <li>中心锥销干涉量: <span class="glow-orange">0.15 mm</span></li>
                <li>初始装配状态: <span class="text-green-400">微间隙滑动配合</span></li>
                <li>最终工作状态: <span class="text-red-400">过盈极压锁死</span></li>
            </ul>
        </div>

        <div class="info-panel desc-panel">
            <h3 class="text-sm font-bold text-white mb-2 flex items-center">
                <svg class="w-4 h-4 mr-2 glow-text" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
                动态机理分析
            </h3>
            <ol class="text-xs space-y-1.5 text-gray-300 list-decimal pl-4">
                <li>带深盲孔与十字开口槽的柔性轴端轻松滑入孔内。</li>
                <li>外部施加轴向载荷打入带有细微锥度的金属锥销。</li>
                <li>锥面产生楔形增力效应,迫使轴端外壁呈“开花状”径向膨胀。</li>
                <li><span class="glow-orange">达成 IFR:</span>孔轴界面由间隙瞬间转为高摩擦力过盈配合,彻底锁死。</li>
            </ol>
        </div>

        <!-- Main SVG Animation -->
        <svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet" id="main-svg">
            <defs>
                <!-- Grid Pattern -->
                <pattern id="blueprintGrid" 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"/>
                    <path d="M 200 0 L 0 0 0 200" fill="none" stroke="var(--grid-color)" stroke-width="1"/>
                </pattern>

                <!-- Metal Hatching for Cutaway Sections -->
                <pattern id="hatchPattern" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
                    <line x1="0" y1="0" x2="0" y2="10" stroke="#2a354d" stroke-width="2" />
                </pattern>

                <!-- Gradients -->
                <linearGradient id="holeMetal" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#151b26"/>
                    <stop offset="100%" stop-color="#222b3d"/>
                </linearGradient>
                <linearGradient id="holeMetalRight" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#222b3d"/>
                    <stop offset="100%" stop-color="#151b26"/>
                </linearGradient>

                <linearGradient id="shaftMetal" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#4a5a75"/>
                    <stop offset="50%" stop-color="#8a9ba8"/>
                    <stop offset="100%" stop-color="#3a475e"/>
                </linearGradient>

                <linearGradient id="pinMetal" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#cc4400"/>
                    <stop offset="50%" stop-color="#ff7733"/>
                    <stop offset="100%" stop-color="#993300"/>
                </linearGradient>

                <!-- Glow Filters -->
                <filter id="glowGlow" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="8" result="blur" />
                    <feMerge>
                        <feMergeNode in="blur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>
            </defs>

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

            <!-- Center Axis Line -->
            <line x1="500" y1="50" x2="500" y2="650" stroke="rgba(0, 240, 255, 0.3)" stroke-width="1" stroke-dasharray="15, 10, 3, 10" />
            <text x="510" y="70" fill="rgba(0, 240, 255, 0.5)" font-size="10" font-family="monospace">CENTER AXIS (CL)</text>

            <g id="scene-container" transform="translate(0, 50)">
                
                <!-- HOLE COMPONENT (Outer shell, cross-section) -->
                <!-- Left Hole Body -->
                <path d="M 200,100 L 416,100 L 416,500 L 200,500 Z" fill="url(#holeMetal)" class="svg-metal-path" />
                <path d="M 200,100 L 416,100 L 416,500 L 200,500 Z" fill="url(#hatchPattern)" opacity="0.6"/>
                <!-- Right Hole Body -->
                <path d="M 800,100 L 584,100 L 584,500 L 800,500 Z" fill="url(#holeMetalRight)" class="svg-metal-path" />
                <path d="M 800,100 L 584,100 L 584,500 L 800,500 Z" fill="url(#hatchPattern)" opacity="0.6"/>

                <text x="220" y="130" fill="rgba(255,255,255,0.3)" font-size="12" font-family="monospace">OUTER HOLE</text>
                <text x="700" y="130" fill="rgba(255,255,255,0.3)" font-size="12" font-family="monospace">OUTER HOLE</text>


                <!-- INITIAL GAP VISUALIZATION (Background lines) -->
                <line x1="418" y1="100" x2="418" y2="400" stroke="#00f0ff" stroke-width="1" opacity="0.3" stroke-dasharray="2,2"/>
                <line x1="582" y1="100" x2="582" y2="400" stroke="#00f0ff" stroke-width="1" opacity="0.3" stroke-dasharray="2,2"/>


                <!-- SHAFT COMPONENT -->
                <!-- Shaft Base (Solid part below the slot) -->
                <path d="M 420,400 L 580,400 L 580,600 L 420,600 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
                <text x="475" y="550" fill="rgba(255,255,255,0.5)" font-size="12" font-family="monospace" letter-spacing="2">MAIN SHAFT</text>

                <!-- Left Expanding Arm (Pivot at 460, 400) -->
                <g id="left-arm">
                    <path d="M 420,100 L 485,100 L 490,400 L 420,400 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
                    <!-- Slot depth indicator -->
                    <line x1="488" y1="100" x2="490" y2="400" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
                </g>

                <!-- Right Expanding Arm (Pivot at 540, 400) -->
                <g id="right-arm">
                    <path d="M 580,100 L 515,100 L 510,400 L 580,400 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
                    <line x1="512" y1="100" x2="510" y2="400" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
                </g>

                <!-- Cross-slot centerline (Visual depth) -->
                <line x1="500" y1="100" x2="500" y2="400" stroke="rgba(0,0,0,0.5)" stroke-width="2" stroke-dasharray="4,2"/>


                <!-- TAPERED PIN -->
                <g id="taper-pin-group">
                    <g id="taper-pin">
                        <!-- Pin Body -->
                        <polygon points="480,-50 520,-50 514,250 486,250" fill="url(#pinMetal)" stroke="#ff9966" stroke-width="1.5" />
                        <!-- Pin Top Cap -->
                        <path d="M 476,-50 L 524,-50 L 524,-60 L 476,-60 Z" fill="#ff7733" />
                        <!-- Force Arrows applied to Pin -->
                        <g id="force-arrows" opacity="0">
                            <path d="M 500,-100 L 500,-70" stroke="var(--accent-orange)" stroke-width="3" stroke-linecap="round" />
                            <polygon points="500,-65 495,-75 505,-75" fill="var(--accent-orange)" />
                            <text x="515" y="-80" fill="var(--accent-orange)" font-size="12" font-family="monospace" font-weight="bold">F (AXIAL LOAD)</text>
                        </g>
                    </g>
                </g>

                <!-- LOCKING HIGHLIGHTS & EFFECTS (Appear on interference) -->
                <g class="lock-indicator" id="lock-effects">
                    <!-- Left Wall Glow -->
                    <line x1="416" y1="100" x2="416" y2="350" stroke="#ff3300" stroke-width="6" filter="url(#glowGlow)" opacity="0.8" />
                    <line x1="416" y1="100" x2="416" y2="350" stroke="#ffffff" stroke-width="2" />
                    
                    <!-- Right Wall Glow -->
                    <line x1="584" y1="100" x2="584" y2="350" stroke="#ff3300" stroke-width="6" filter="url(#glowGlow)" opacity="0.8" />
                    <line x1="584" y1="100" x2="584" y2="350" stroke="#ffffff" stroke-width="2" />

                    <!-- Radial Force Arrows (Internal) -->
                    <g opacity="0.8" stroke="var(--text-accent)" stroke-width="1.5" fill="none">
                        <!-- Left pushes -->
                        <path d="M 480,150 L 430,150" marker-end="url(#arrowCyan)"/>
                        <path d="M 483,250 L 430,250" marker-end="url(#arrowCyan)"/>
                        <path d="M 486,350 L 430,350" marker-end="url(#arrowCyan)"/>
                        
                        <!-- Right pushes -->
                        <path d="M 520,150 L 570,150" marker-end="url(#arrowCyan)"/>
                        <path d="M 517,250 L 570,250" marker-end="url(#arrowCyan)"/>
                        <path d="M 514,350 L 570,350" marker-end="url(#arrowCyan)"/>
                    </g>

                    <text x="320" y="250" fill="#ff5500" font-size="12" font-family="monospace" font-weight="bold" filter="url(#glowGlow)">↑ INTERFERENCE FIT</text>
                    <text x="680" y="250" fill="#ff5500" font-size="12" font-family="monospace" font-weight="bold" filter="url(#glowGlow)">INTERFERENCE FIT ↑</text>
                </g>

            </g>

            <!-- Markers definition (must be outside scaled groups or carefully managed) -->
            <defs>
                <marker id="arrowCyan" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
                    <path d="M 0 1 L 10 5 L 0 9 z" fill="var(--text-accent)" />
                </marker>
            </defs>

            <!-- Dimension Lines (Static UI layer in SVG) -->
            <g stroke="rgba(163, 184, 204, 0.4)" stroke-width="1" fill="none" font-family="monospace" font-size="10" text-anchor="middle">
                <!-- Slot Length -->
                <line x1="390" y1="150" x2="390" y2="450" />
                <line x1="385" y1="150" x2="395" y2="150" />
                <line x1="385" y1="450" x2="395" y2="450" />
                <text x="375" y="305" fill="rgba(163, 184, 204, 0.8)" transform="rotate(-90, 375, 305)">SLOT LENGTH ≈ 1.5D</text>

                <!-- Initial Clearance (Exaggerated for diagram) -->
                <line x1="416" y1="80" x2="416" y2="90" />
                <line x1="420" y1="80" x2="420" y2="90" />
                <line x1="416" y1="85" x2="400" y2="85" />
                <line x1="420" y1="85" x2="436" y2="85" />
                <text x="418" y="75" fill="rgba(0, 240, 255, 0.8)">CLEARANCE</text>
            </g>

        </svg>
    </div>

    <script>
        document.addEventListener("DOMContentLoaded", () => {
            const pin = document.getElementById('taper-pin');
            const leftArm = document.getElementById('left-arm');
            const rightArm = document.getElementById('right-arm');
            const forceArrows = document.getElementById('force-arrows');
            const lockEffects = document.getElementById('lock-effects');
            
            // Animation Parameters
            const cycleDuration = 4000; // Total ms per cycle (down, hold, up, hold)
            
            // Physical boundaries in SVG space
            const pinStartY = -100;
            const pinEndY = 150; // Pin descends 250 units
            const maxAngle = 1.2; // Degrees arms rotate outwards to close the gap

            // Arm Pivots
            const leftPivotX = 460;
            const rightPivotX = 540;
            const pivotY = 400;

            let startTimestamp = null;

            function easeInOutCubic(t) {
                return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
            }

            function animate(timestamp) {
                if (!startTimestamp) startTimestamp = timestamp;
                
                // Progress from 0 to 1 over the cycle duration
                const elapsed = timestamp - startTimestamp;
                const rawProgress = (elapsed % cycleDuration) / cycleDuration;
                
                // Create a timeline within the cycle:
                // 0.0 - 0.1: Hold top
                // 0.1 - 0.4: Drive pin down (expand)
                // 0.4 - 0.6: Hold bottom (locked state, IFR)
                // 0.6 - 0.9: Pull pin up (retract)
                // 0.9 - 1.0: Hold top
                
                let motionPhase = 0; // 0 (top) to 1 (bottom)
                let isLocked = false;

                if (rawProgress < 0.1) {
                    motionPhase = 0;
                } else if (rawProgress < 0.4) {
                    const localP = (rawProgress - 0.1) / 0.3;
                    motionPhase = easeInOutCubic(localP);
                } else if (rawProgress < 0.6) {
                    motionPhase = 1;
                    isLocked = true;
                } else if (rawProgress < 0.9) {
                    const localP = (rawProgress - 0.6) / 0.3;
                    motionPhase = 1 - easeInOutCubic(localP);
                } else {
                    motionPhase = 0;
                }

                // Calculate positions based on phase
                const currentPinY = pinStartY + (pinEndY - pinStartY) * motionPhase;
                const currentAngle = maxAngle * motionPhase;

                // Apply Transforms
                pin.setAttribute('transform', `translate(0, ${currentPinY})`);
                
                // Left arm rotates counter-clockwise (-), Right arm clockwise (+)
                leftArm.setAttribute('transform', `rotate(${-currentAngle}, ${leftPivotX}, ${pivotY})`);
                rightArm.setAttribute('transform', `rotate(${currentAngle}, ${rightPivotX}, ${pivotY})`);

                // UI Opacity Updates
                // Force arrows appear while driving down (0.1 to 0.4)
                if (rawProgress >= 0.1 && rawProgress <= 0.4) {
                    const p = (rawProgress - 0.1) / 0.3;
                    forceArrows.style.opacity = Math.sin(p * Math.PI); // Fade in and out
                } else {
                    forceArrows.style.opacity = 0;
                }

                // Lock effects pulse when locked
                if (isLocked) {
                    // Quick fade in, then hold
                    const lockTime = (rawProgress - 0.4) / 0.2; // 0 to 1 during lock phase
                    // Add a slight pulse effect
                    const pulse = 0.8 + 0.2 * Math.sin(lockTime * Math.PI * 4);
                    lockEffects.style.opacity = pulse;
                } else if (rawProgress > 0.35 && rawProgress < 0.4) {
                    // Quick fade in right before lock
                    lockEffects.style.opacity = (rawProgress - 0.35) / 0.05;
                } else if (rawProgress > 0.6 && rawProgress < 0.65) {
                    // Quick fade out right after lock
                    lockEffects.style.opacity = 1 - ((rawProgress - 0.6) / 0.05);
                } else {
                    lockEffects.style.opacity = 0;
                }

                requestAnimationFrame(animate);
            }

            // Start animation loop
            requestAnimationFrame(animate);
        });
    </script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分