分享图
动画工坊
引擎就绪
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>热膨胀差动自锁机构原理演示</title>
    <style>
        :root {
            --bg-color: #07090F;
            --grid-color: rgba(30, 41, 59, 0.5);
            --text-main: #E2E8F0;
            --text-dim: #64748B;
            --color-cold: #00F0FF;
            --color-hot: #FF2A55;
            --color-seat: #1E293B;
            --color-reflector: #334155;
            --font-tech: 'Courier New', Courier, monospace;
        }

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

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

        #app-container {
            position: relative;
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        svg {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 800px;
        }

        /* 绝对定位的极简文字说明,置于边缘 */
        .overlay-text {
            position: absolute;
            pointer-events: none;
            z-index: 10;
        }

        .header-info {
            top: 24px;
            left: 32px;
        }

        .header-title {
            font-size: 14px;
            font-weight: 600;
            letter-spacing: 2px;
            color: #fff;
            margin-bottom: 4px;
            text-transform: uppercase;
        }

        .header-desc {
            font-size: 11px;
            color: var(--text-dim);
            max-width: 300px;
            line-height: 1.4;
        }

        .status-panel {
            bottom: 32px;
            right: 32px;
            text-align: right;
            font-family: var(--font-tech);
        }

        .temp-display {
            font-size: 32px;
            font-weight: bold;
            color: var(--color-cold);
            text-shadow: 0 0 10px rgba(0, 240, 255, 0.5);
            transition: color 0.3s, text-shadow 0.3s;
        }

        .state-display {
            font-size: 12px;
            color: var(--text-main);
            margin-top: 4px;
            letter-spacing: 1px;
        }

        .legend-panel {
            bottom: 32px;
            left: 32px;
            font-size: 11px;
            color: var(--text-dim);
            display: flex;
            flex-direction: column;
            gap: 6px;
        }

        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .legend-color {
            width: 12px;
            height: 4px;
            border-radius: 2px;
        }
        
        .triz-badge {
            position: absolute;
            top: 24px;
            right: 32px;
            font-size: 10px;
            border: 1px solid rgba(255,255,255,0.2);
            padding: 4px 8px;
            border-radius: 4px;
            color: #A0AABF;
            letter-spacing: 1px;
            background: rgba(0,0,0,0.5);
        }
    </style>
</head>
<body>

    <div id="app-container">
        <!-- 边缘文字信息 -->
        <div class="overlay-text header-info">
            <div class="header-title">热膨胀差动自锁机构</div>
            <div class="header-desc">利用高/低膨胀合金的热变形差,实现无活动部件的温度自驱动锁紧与脱开。</div>
        </div>

        <div class="overlay-text triz-badge">
            TRIZ: 最终理想解 (IFR) & 资源利用
        </div>

        <div class="overlay-text legend-panel">
            <div class="legend-item">
                <div class="legend-color" style="background: #334155;"></div>
                <span>低膨胀锥形环座 (固定, CTE≈6×10⁻⁶/℃)</span>
            </div>
            <div class="legend-item">
                <div class="legend-color" style="background: linear-gradient(90deg, #00F0FF, #FF2A55);"></div>
                <span>高膨胀分瓣锁环 (CTE≈17×10⁻⁶/℃)</span>
            </div>
        </div>

        <div class="overlay-text status-panel">
            <div class="temp-display" id="temp-val">150°C</div>
            <div class="state-display" id="state-val">系统就绪 / 间隙态</div>
        </div>

        <!-- 主体SVG动画区域 -->
        <svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <!-- 网格背景图案 -->
                <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>

                <!-- 金属渐变材质 -->
                <linearGradient id="grad-seat" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#0F172A" />
                    <stop offset="50%" stop-color="#1E293B" />
                    <stop offset="100%" stop-color="#0F172A" />
                </linearGradient>
                
                <linearGradient id="grad-reflector" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#1E293B" />
                    <stop offset="50%" stop-color="#475569" />
                    <stop offset="100%" stop-color="#1E293B" />
                </linearGradient>

                <!-- 锁环的动态颜色渐变 (冷态) -->
                <linearGradient id="grad-ring-cold" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#0088AA" />
                    <stop offset="100%" stop-color="#00F0FF" />
                </linearGradient>

                <!-- 发光滤镜 -->
                <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>
                <filter id="glow-cold" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>

                <!-- 箭头标记 -->
                <marker id="arrowhead-red" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
                    <polygon points="0 0, 6 3, 0 6" fill="#FF2A55" />
                </marker>
                <marker id="arrowhead-cyan" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
                    <polygon points="0 0, 6 3, 0 6" fill="#00F0FF" />
                </marker>
            </defs>

            <!-- 背景网格 -->
            <rect width="100%" height="100%" fill="url(#grid)" />

            <!-- ================= 主剖视图 (中心) ================= -->
            <g transform="translate(500, 300)">
                <!-- 中心线 -->
                <line x1="0" y1="-250" x2="0" y2="250" stroke="rgba(255,255,255,0.1)" stroke-width="1" stroke-dasharray="10 5" />
                <text x="5" y="-240" fill="rgba(255,255,255,0.3)" font-size="10" font-family="monospace">CL</text>

                <!-- 固定的低膨胀锥形环座 (左右对称) -->
                <!-- 角度被适度夸大以展示原理 (理论4度,视觉呈现约10度) -->
                <path d="M -220,-150 L -120,-150 L -90,150 L -220,150 Z" fill="url(#grad-seat)" stroke="#475569" stroke-width="1"/>
                <path d="M 220,-150 L 120,-150 L 90,150 L 220,150 Z" fill="url(#grad-seat)" stroke="#475569" stroke-width="1"/>
                
                <!-- 环座标注 -->
                <text x="-210" y="-130" fill="#64748B" font-size="10">固定支承</text>
                
                <!-- === 动态组件组 (随提取动作上下移动) === -->
                <g id="moving-assembly" transform="translate(0, 0)">
                    <!-- 中心反射体底部法兰 -->
                    <rect x="-70" y="-250" width="140" height="400" fill="url(#grad-reflector)" rx="2"/>
                    <!-- 限位挡台 -->
                    <rect x="-90" y="80" width="180" height="20" fill="#1E293B" stroke="#334155" stroke-width="1"/>
                    
                    <!-- 高膨胀分瓣锁环 (左) -->
                    <!-- 初始状态:靠内,与锥座有间隙 -->
                    <g id="lock-ring-left" transform="translate(0, 0)">
                        <path d="M -70,-50 L -100,-50 L -78,110 L -70,110 Z" fill="#0088AA" id="ring-path-left" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
                        <!-- 周向收紧弹簧剖面示意 (圆点) -->
                        <circle cx="-88" cy="30" r="3" fill="#94A3B8" />
                    </g>

                    <!-- 高膨胀分瓣锁环 (右) -->
                    <g id="lock-ring-right" transform="translate(0, 0)">
                        <path d="M 70,-50 L 100,-50 L 78,110 L 70,110 Z" fill="#0088AA" id="ring-path-right" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
                        <circle cx="88" cy="30" r="3" fill="#94A3B8" />
                    </g>
                </g>

                <!-- 交互动态指示图元 -->
                <g id="indicators">
                    <!-- 间隙指示 (冷态显示) -->
                    <g id="gap-indicator" opacity="1">
                        <line x1="-105" y1="0" x2="-85" y2="0" stroke="#00F0FF" stroke-width="1" marker-end="url(#arrowhead-cyan)" marker-start="url(#arrowhead-cyan)"/>
                        <text x="-140" y="4" fill="#00F0FF" font-size="10" font-family="monospace">0.10mm 间隙</text>
                    </g>

                    <!-- 过盈/压力指示 (热态显示) -->
                    <g id="force-indicator" opacity="0">
                        <!-- 楔入法向力指示 -->
                        <line x1="-120" y1="20" x2="-95" y2="25" stroke="#FF2A55" stroke-width="2" marker-end="url(#arrowhead-red)"/>
                        <line x1="120" y1="20" x2="95" y2="25" stroke="#FF2A55" stroke-width="2" marker-end="url(#arrowhead-red)"/>
                        
                        <!-- 摩擦力/锁死指示 -->
                        <line x1="-110" y1="-10" x2="-110" y2="-40" stroke="#FF2A55" stroke-width="2" marker-end="url(#arrowhead-red)"/>
                        <line x1="110" y1="-10" x2="110" y2="-40" stroke="#FF2A55" stroke-width="2" marker-end="url(#arrowhead-red)"/>
                        
                        <text x="-160" y="-20" fill="#FF2A55" font-size="11" font-weight="bold">自锁力 (IFR)</text>
                    </g>
                </g>
            </g>

            <!-- ================= 俯视图小窗 (右侧) ================= -->
            <!-- 用于展示8瓣分瓣结构和周向膨胀 -->
            <g transform="translate(820, 150)">
                <rect x="-80" y="-80" width="160" height="160" fill="rgba(15, 23, 42, 0.5)" rx="8" stroke="rgba(255,255,255,0.05)"/>
                <text x="0" y="-60" fill="#64748B" font-size="10" text-anchor="middle">A-A 俯视切面 (8瓣结构)</text>
                
                <!-- 固定外环座 -->
                <circle cx="0" cy="0" r="50" fill="none" stroke="#334155" stroke-width="6"/>
                
                <!-- 动态8瓣锁环组 -->
                <g id="top-view-rings">
                    <!-- 通过JS动态生成8个扇形 -->
                </g>
                
                <!-- 中心轴 -->
                <circle cx="0" cy="0" r="30" fill="#475569" />
            </g>

            <!-- ================= 能量/热量流指示 ================= -->
            <g id="heat-waves" opacity="0">
                <path d="M 300 450 Q 350 400 320 350" fill="none" stroke="#FF2A55" stroke-width="2" opacity="0.5" stroke-dasharray="5 5">
                    <animate attributeName="stroke-dashoffset" from="100" to="0" dur="2s" repeatCount="indefinite" />
                </path>
                <path d="M 700 450 Q 650 400 680 350" fill="none" stroke="#FF2A55" stroke-width="2" opacity="0.5" stroke-dasharray="5 5">
                    <animate attributeName="stroke-dashoffset" from="100" to="0" dur="2s" repeatCount="indefinite" />
                </path>
            </g>

        </svg>
    </div>

    <script>
        // 核心参数设定
        const TEMP_MIN = 150;
        const TEMP_MAX = 300;
        const EXPANSION_MAX = 12; // 视觉上的最大径向膨胀量(像素)
        const EXTRACT_Y = -180;   // 拔出时的Y轴位移

        // DOM 元素引用
        const domTemp = document.getElementById('temp-val');
        const domState = document.getElementById('state-val');
        const assembly = document.getElementById('moving-assembly');
        const ringLeft = document.getElementById('lock-ring-left');
        const ringRight = document.getElementById('lock-ring-right');
        const pathLeft = document.getElementById('ring-path-left');
        const pathRight = document.getElementById('ring-path-right');
        const gapIndicator = document.getElementById('gap-indicator');
        const forceIndicator = document.getElementById('force-indicator');
        const heatWaves = document.getElementById('heat-waves');
        const topViewRings = document.getElementById('top-view-rings');

        // 生成俯视图的8瓣结构
        function initTopView() {
            const segments = 8;
            const angleStep = 360 / segments;
            for(let i=0; i<segments; i++) {
                const group = document.createElementNS("http://www.w3.org/2000/svg", "g");
                const rotation = i * angleStep;
                group.setAttribute("transform", `rotate(${rotation})`);
                
                // 绘制单个扇形 (简化的多边形表示)
                const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
                // r_inner=32, r_outer=42, span=40deg
                path.setAttribute("d", "M 6.4,-31 L 8.4,-41 L 28,-30 L 21,-22 Z"); // 近似参数
                path.setAttribute("fill", "#0088AA");
                path.classList.add('top-ring-segment');
                path.setAttribute("stroke", "rgba(0,0,0,0.5)");
                path.setAttribute("stroke-width", "1");
                
                group.appendChild(path);
                topViewRings.appendChild(group);
            }
        }
        initTopView();

        // 颜色插值辅助函数 (RGB)
        function interpolateColor(color1, color2, factor) {
            const result = color1.slice();
            for (let i = 0; i < 3; i++) {
                result[i] = Math.round(result[i] + factor * (color2[i] - color1[i]));
            }
            return `rgb(${result[0]}, ${result[1]}, ${result[2]})`;
        }

        const colorCyan = [0, 240, 255];
        const colorRed = [255, 42, 85];
        const colorCyanDark = [0, 136, 170];
        const colorRedDark = [200, 30, 60];

        // 动画时间轴定义
        const timeline = [
            { time: 0,     temp: 150, y: 0, state: "运行/冷态 (间隙存在)" },
            { time: 2000,  temp: 150, y: 0, state: "开始升温..." },
            { time: 5000,  temp: 300, y: 0, state: "高温膨胀楔入" },
            { time: 8000,  temp: 300, y: 0, state: "热自锁状态 (最终理想解)" },
            { time: 10000, temp: 150, y: 0, state: "停堆降温..." },
            { time: 13000, temp: 150, y: 0, state: "冷态收缩 (间隙恢复)" },
            { time: 14000, temp: 150, y: 0, state: "准备拔出" },
            { time: 16000, temp: 150, y: EXTRACT_Y, state: "无干涉拔出" },
            { time: 18000, temp: 150, y: EXTRACT_Y, state: "拔出完成" },
            { time: 20000, temp: 150, y: 0, state: "重新装入" },
            { time: 21000, temp: 150, y: 0, state: "运行/冷态 (间隙存在)" } // 闭环
        ];

        const TOTAL_DURATION = timeline[timeline.length - 1].time;
        let startTime = null;

        // 核心动画循环
        function animate(timestamp) {
            if (!startTime) startTime = timestamp;
            let elapsed = (timestamp - startTime) % TOTAL_DURATION;

            // 查找当前所处的时间段
            let currentFrame = timeline[0];
            let nextFrame = timeline[1];
            for (let i = 0; i < timeline.length - 1; i++) {
                if (elapsed >= timeline[i].time && elapsed < timeline[i+1].time) {
                    currentFrame = timeline[i];
                    nextFrame = timeline[i+1];
                    break;
                }
            }

            // 计算插值因子 (0 到 1)
            const progress = (elapsed - currentFrame.time) / (nextFrame.time - currentFrame.time);
            
            // 缓动函数 (Ease-in-out)
            const easeProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;

            // 计算当前属性值
            const currentTemp = currentFrame.temp + (nextFrame.temp - currentFrame.temp) * easeProgress;
            const currentY = currentFrame.y + (nextFrame.y - currentFrame.y) * easeProgress;
            
            // 归一化温度系数 (0 = 150C, 1 = 300C)
            const tempFactor = (currentTemp - TEMP_MIN) / (TEMP_MAX - TEMP_MIN);
            
            // 径向膨胀量
            const expansion = tempFactor * EXPANSION_MAX;

            // 更新 DOM
            // 1. 文字与状态
            domTemp.innerText = `${Math.round(currentTemp)}°C`;
            if (Math.round(currentTemp) > 220) {
                domTemp.style.color = 'var(--color-hot)';
                domTemp.style.textShadow = '0 0 10px rgba(255, 42, 85, 0.6)';
            } else {
                domTemp.style.color = 'var(--color-cold)';
                domTemp.style.textShadow = '0 0 10px rgba(0, 240, 255, 0.5)';
            }
            domState.innerText = currentFrame.state;

            // 2. 位置位移
            assembly.setAttribute('transform', `translate(0, ${currentY})`);
            ringLeft.setAttribute('transform', `translate(${-expansion}, 0)`);
            ringRight.setAttribute('transform', `translate(${expansion}, 0)`);

            // 3. 颜色与发光
            const fillColor = interpolateColor(colorCyanDark, colorRedDark, tempFactor);
            pathLeft.setAttribute('fill', fillColor);
            pathRight.setAttribute('fill', fillColor);
            
            if (tempFactor > 0.8) {
                pathLeft.setAttribute('filter', 'url(#glow-hot)');
                pathRight.setAttribute('filter', 'url(#glow-hot)');
                heatWaves.setAttribute('opacity', '1');
            } else {
                pathLeft.setAttribute('filter', 'url(#glow-cold)');
                pathRight.setAttribute('filter', 'url(#glow-cold)');
                heatWaves.setAttribute('opacity', '0');
            }

            // 4. 指示器透明度切换
            // 当温度升高,间隙消失,过盈力出现
            gapIndicator.setAttribute('opacity', 1 - tempFactor);
            // 只有当完全在底部且温度高时才显示力 (Y需接近0)
            const isSeated = currentY > -10;
            forceIndicator.setAttribute('opacity', isSeated ? tempFactor : 0);

            // 5. 更新俯视图的8瓣展开
            const segments = document.querySelectorAll('.top-ring-segment');
            segments.forEach(seg => {
                seg.setAttribute('fill', fillColor);
                // 使用transform做微小向外平移模拟径向膨胀
                seg.setAttribute('transform', `translate(0, ${-tempFactor * 3})`);
            });

            requestAnimationFrame(animate);
        }

        // 页面加载完成后自动触发动画
        window.addEventListener('DOMContentLoaded', () => {
            requestAnimationFrame(animate);
        });

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