分享图
动画工坊
引擎就绪
<!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>
        /* 全局与布局重置 */
        body, html {
            margin: 0;
            padding: 0;
            width: 100vw;
            height: 100vh;
            background-color: #0A0F1A;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
        }

        /* 动画容器 */
        .svg-container {
            width: 100%;
            height: 100%;
            max-width: 1200px;
            max-height: 800px;
            position: relative;
        }

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

        /* CSS 动画定义 */
        @keyframes sparkFlicker {
            0%, 100% { opacity: 0; transform: scale(0.5); }
            50% { opacity: 1; transform: scale(1.2); }
            25%, 75% { opacity: 0.8; transform: scale(0.8); }
        }

        @keyframes prepPulse {
            0%, 100% { fill-opacity: 0.1; stroke-opacity: 0.5; }
            50% { fill-opacity: 0.3; stroke-opacity: 1; }
        }

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

        /* 动态类 */
        .cart {
            transition: transform 1.2s cubic-bezier(0.4, 0.0, 0.2, 1);
        }
        
        .frame-group {
            transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
        }

        .sparks path {
            opacity: 0;
            transform-origin: center top;
        }

        .is-welding .sparks path {
            animation: sparkFlicker 0.1s infinite alternate;
        }
        
        .is-welding .welding-beam {
            opacity: 0.8;
            transition: opacity 0.3s;
        }

        .welding-beam {
            opacity: 0;
            transition: opacity 0.3s;
        }

        .is-prepping .prep-glow {
            animation: prepPulse 2s infinite;
        }

        .track-line {
            stroke-dasharray: 4 6;
            animation: dashScroll 1s linear infinite;
        }

    </style>
</head>
<body>

    <div class="svg-container">
        <svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet" id="main-svg">
            <defs>
                <!-- 背景网格 -->
                <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
                    <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#1E293B" stroke-width="0.5"/>
                </pattern>
                
                <!-- 渐变与发光滤镜 -->
                <linearGradient id="frameGrad" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="#334155" />
                    <stop offset="100%" stop-color="#0F172A" />
                </linearGradient>

                <linearGradient id="beamGrad" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="#06B6D4" stop-opacity="0.8"/>
                    <stop offset="100%" stop-color="#06B6D4" stop-opacity="0"/>
                </linearGradient>

                <filter id="neonGlowA" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="neonGlowB" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="4" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="sparkGlow" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="3" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
            </defs>

            <!-- 背景层 -->
            <rect width="1000" height="600" fill="url(#grid)" />
            
            <!-- 边缘小字号说明与装饰 (绝对不遮挡核心区) -->
            <g font-size="12" fill="#64748B" font-family="monospace">
                <text x="30" y="30">SYS.STATE // DUAL_SLOT_SHUTTLE_ACTIVE</text>
                <text x="30" y="50">IFR.TARGET // WAIT_TIME_ELIMINATED</text>
                <text x="970" y="30" text-anchor="end">RESOURCE // FRONT_REAR_IDLE_SPACE_UTILIZED</text>
                
                <!-- 右下角 IFR 面板 -->
                <rect x="760" y="510" width="220" height="70" rx="4" fill="#0F172A" stroke="#1E293B" stroke-width="1"/>
                <text x="775" y="530" fill="#38BDF8" font-size="12" font-weight="bold">最终理想解 (IFR) 指标</text>
                <text x="775" y="550" fill="#94A3B8" font-size="11">• 矛盾消除: 备料/焊接由串行转并行</text>
                <text x="775" y="565" fill="#94A3B8" font-size="11">• 资源利用: 极小改造利用原有闲置空间</text>
            </g>

            <!-- 核心状态指示器 (顶部居中,小字号) -->
            <g id="ui-status" transform="translate(500, 60)" text-anchor="middle">
                <rect x="-180" y="-20" width="360" height="30" rx="15" fill="#1E293B" opacity="0.8" stroke="#334155"/>
                <circle cx="-160" cy="-5" r="4" id="status-indicator" fill="#10B981" />
                <text x="-145" y="0" id="status-text" fill="#E2E8F0" font-size="13" text-anchor="start" font-weight="500">系统初始化...</text>
            </g>

            <!-- 场景静物:双轨与支架 -->
            <g id="environment" transform="translate(0, 0)">
                <!-- 后方轨道 (A槽主要活动区) -->
                <line x1="150" y1="420" x2="850" y2="420" stroke="#1E293B" stroke-width="6" stroke-linecap="round"/>
                <line x1="150" y1="420" x2="850" y2="420" stroke="#38BDF8" stroke-width="2" class="track-line" stroke-linecap="round" opacity="0.3"/>
                <text x="150" y="440" fill="#475569" font-size="12">REAR_PREP_ZONE (后方/备料下料)</text>

                <!-- 前方轨道 (B槽主要活动区) -->
                <line x1="150" y1="480" x2="850" y2="480" stroke="#1E293B" stroke-width="6" stroke-linecap="round"/>
                <line x1="150" y1="480" x2="850" y2="480" stroke="#F59E0B" stroke-width="2" class="track-line" stroke-linecap="round" opacity="0.3"/>
                <text x="660" y="500" fill="#475569" font-size="12">FRONT_PREP_ZONE (前方/备料下料)</text>
                
                <!-- 焊接中心基座 -->
                <rect x="420" y="490" width="160" height="20" rx="2" fill="#1E293B" stroke="#0F172A"/>
                <path d="M 460 490 L 480 510 L 520 510 L 540 490" fill="#0F172A"/>
                <text x="500" y="525" fill="#94A3B8" font-size="12" text-anchor="middle">WELDING_CENTER</text>
            </g>

            <!-- 动态元件:槽台车 A -->
            <!-- 初始位置:X=500 (中间), Y=400 (后轨上) -->
            <g id="cart-A" class="cart" transform="translate(500, 400)">
                <rect class="prep-glow" x="-70" y="-30" width="140" height="40" rx="4" fill="#0EA5E9" fill-opacity="0.1" stroke="#0EA5E9" stroke-width="1.5" filter="url(#neonGlowA)"/>
                <!-- 内部工件示意 -->
                <path d="M -50 -10 L -30 -20 L 30 -20 L 50 -10 L 50 0 L -50 0 Z" fill="#334155" stroke="#475569" stroke-width="1"/>
                <rect x="-65" y="10" width="130" height="8" rx="2" fill="#0F172A"/>
                <!-- 轮子 -->
                <circle cx="-50" cy="20" r="6" fill="#64748B" stroke="#0F172A" stroke-width="2"/>
                <circle cx="50" cy="20" r="6" fill="#64748B" stroke="#0F172A" stroke-width="2"/>
                <!-- 标识 -->
                <rect x="-15" y="-6" width="30" height="14" rx="2" fill="#0EA5E9"/>
                <text x="0" y="4" fill="#0F172A" font-size="10" font-weight="bold" text-anchor="middle">槽 A</text>
                
                <!-- 备料状态悬浮文字 -->
                <text class="status-lbl" x="0" y="-40" fill="#0EA5E9" font-size="11" text-anchor="middle" opacity="0">下料与备料中</text>
            </g>

            <!-- 动态元件:槽台车 B -->
            <!-- 初始位置:X=800 (右侧), Y=460 (前轨上) -->
            <g id="cart-B" class="cart" transform="translate(800, 460)">
                <rect class="prep-glow" x="-70" y="-30" width="140" height="40" rx="4" fill="#F59E0B" fill-opacity="0.1" stroke="#F59E0B" stroke-width="1.5" filter="url(#neonGlowB)"/>
                <!-- 内部工件示意 -->
                <path d="M -50 -10 L -30 -20 L 30 -20 L 50 -10 L 50 0 L -50 0 Z" fill="#334155" stroke="#475569" stroke-width="1"/>
                <rect x="-65" y="10" width="130" height="8" rx="2" fill="#0F172A"/>
                <!-- 轮子 -->
                <circle cx="-50" cy="20" r="6" fill="#64748B" stroke="#0F172A" stroke-width="2"/>
                <circle cx="50" cy="20" r="6" fill="#64748B" stroke="#0F172A" stroke-width="2"/>
                <!-- 标识 -->
                <rect x="-15" y="-6" width="30" height="14" rx="2" fill="#F59E0B"/>
                <text x="0" y="4" fill="#0F172A" font-size="10" font-weight="bold" text-anchor="middle">槽 B</text>

                <!-- 备料状态悬浮文字 -->
                <text class="status-lbl" x="0" y="-40" fill="#F59E0B" font-size="11" text-anchor="middle" opacity="0">下料与备料中</text>
            </g>

            <!-- 顶部压力架与焊枪 (Y轴移动) -->
            <g id="pressure-sys">
                <!-- 固定的垂直立柱 -->
                <rect x="360" y="100" width="16" height="300" fill="#1E293B" rx="2"/>
                <rect x="624" y="100" width="16" height="300" fill="#1E293B" rx="2"/>
                <line x1="368" y1="100" x2="368" y2="400" stroke="#0F172A" stroke-width="4" stroke-dasharray="10 10"/>
                <line x1="632" y1="100" x2="632" y2="400" stroke="#0F172A" stroke-width="4" stroke-dasharray="10 10"/>

                <!-- 升降压力架与焊枪组 -->
                <g id="pressure-frame" class="frame-group" transform="translate(0, 100)"> <!-- Y range: 100(UP) to 210(DOWN) -->
                    <!-- 横梁 -->
                    <rect x="340" y="150" width="320" height="30" rx="4" fill="url(#frameGrad)" stroke="#475569" stroke-width="2"/>
                    <rect x="350" y="160" width="300" height="10" rx="2" fill="#0F172A"/>
                    
                    <!-- 压板结构 -->
                    <path d="M 400 180 L 420 220 L 580 220 L 600 180 Z" fill="#334155" opacity="0.8"/>
                    <line x1="420" y1="220" x2="580" y2="220" stroke="#06B6D4" stroke-width="2" opacity="0.5"/>

                    <!-- 焊枪头 -->
                    <path d="M 490 180 L 510 180 L 505 210 L 500 230 L 495 210 Z" fill="#64748B" stroke="#94A3B8" stroke-width="1"/>
                    <circle cx="500" cy="230" r="3" fill="#06B6D4"/>

                    <!-- 焊接光束 -->
                    <polygon points="498,230 502,230 515,300 485,300" class="welding-beam" fill="url(#beamGrad)" />

                    <!-- 飞溅火花组 (默认隐藏,通过 class 激活) -->
                    <g class="sparks" transform="translate(500, 230)" filter="url(#sparkGlow)">
                        <path d="M 0 0 L -15 30" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" />
                        <path d="M 0 0 L 10 35" stroke="#06B6D4" stroke-width="2.5" stroke-linecap="round" style="animation-delay: 0.05s" />
                        <path d="M 0 0 L -25 25" stroke="#38BDF8" stroke-width="1.5" stroke-linecap="round" style="animation-delay: 0.02s" />
                        <path d="M 0 0 L 20 28" stroke="#F59E0B" stroke-width="2" stroke-linecap="round" style="animation-delay: 0.07s" />
                        <path d="M 0 0 L 0 40" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" style="animation-delay: 0.04s" />
                    </g>
                </g>
            </g>
            
        </svg>
    </div>

    <script>
        document.addEventListener("DOMContentLoaded", () => {
            const cartA = document.getElementById('cart-A');
            const cartB = document.getElementById('cart-B');
            const frame = document.getElementById('pressure-frame');
            const statusText = document.getElementById('status-text');
            const statusIndicator = document.getElementById('status-indicator');
            const pressureSys = document.getElementById('pressure-sys');

            // 坐标定义 (中心对齐)
            const POS_CENTER = 500;
            const POS_LEFT = 200;  // 后方备料区
            const POS_RIGHT = 800; // 前方备料区
            
            // 垂直位置定义
            const FRAME_UP = 100;
            const FRAME_DOWN = 160;

            // 辅助函数
            const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));

            const updateStatus = (text, color) => {
                statusText.textContent = text;
                statusIndicator.setAttribute('fill', color);
            };

            const togglePrepStatus = (cartNode, isPrepping) => {
                if(isPrepping) {
                    cartNode.classList.add('is-prepping');
                    cartNode.querySelector('.status-lbl').style.opacity = 1;
                } else {
                    cartNode.classList.remove('is-prepping');
                    cartNode.querySelector('.status-lbl').style.opacity = 0;
                }
            }

            // 核心控制时序 (无限循环)
            async function runCycle() {
                // 初始状态强制重置
                cartA.style.transform = `translate(${POS_CENTER}px, 400px)`;
                cartB.style.transform = `translate(${POS_RIGHT}px, 460px)`;
                frame.style.transform = `translate(0px, ${FRAME_UP}px)`;
                await wait(500);

                while (true) {
                    // ---- 阶段 1: A槽压紧焊接 / B槽前置备料 ----
                    updateStatus("时序动作: 压力架下压锁定...", "#F59E0B");
                    frame.style.transform = `translate(0px, ${FRAME_DOWN}px)`;
                    await wait(800); // 等待下压完成

                    updateStatus("IFR并行: A槽自动焊接 中 / B槽同步 备料", "#06B6D4");
                    pressureSys.classList.add('is-welding');
                    togglePrepStatus(cartB, true);
                    
                    // 模拟耗时的焊接与备料并行过程
                    await wait(3500); 

                    // 焊接完成
                    pressureSys.classList.remove('is-welding');
                    togglePrepStatus(cartB, false);
                    updateStatus("时序动作: A槽焊接完成, 压力架抬起解锁", "#F59E0B");
                    
                    // ---- 阶段 2: 解锁与穿梭互换 ----
                    frame.style.transform = `translate(0px, ${FRAME_UP}px)`;
                    await wait(800); // 等待抬起

                    updateStatus("核心机构: 双槽前后穿梭位移切换 (<30s)", "#8B5CF6");
                    // A退到左侧(后方), B推入中心
                    cartA.style.transform = `translate(${POS_LEFT}px, 400px)`;
                    cartB.style.transform = `translate(${POS_CENTER}px, 460px)`;
                    await wait(1500); // 穿梭位移时间

                    // ---- 阶段 3: B槽压紧焊接 / A槽后置下料备料 ----
                    updateStatus("时序动作: 压力架下压锁定...", "#F59E0B");
                    frame.style.transform = `translate(0px, ${FRAME_DOWN}px)`;
                    await wait(800);

                    updateStatus("IFR并行: B槽自动焊接 中 / A槽同步 下料及备料", "#06B6D4");
                    pressureSys.classList.add('is-welding');
                    togglePrepStatus(cartA, true);

                    await wait(3500);

                    // 焊接完成
                    pressureSys.classList.remove('is-welding');
                    togglePrepStatus(cartA, false);
                    updateStatus("时序动作: B槽焊接完成, 压力架抬起解锁", "#F59E0B");

                    // ---- 阶段 4: 解锁与穿梭互换(复位) ----
                    frame.style.transform = `translate(0px, ${FRAME_UP}px)`;
                    await wait(800);

                    updateStatus("核心机构: 双槽前后穿梭位移切换 (<30s)", "#8B5CF6");
                    // B退到右侧(前方), A推入中心
                    cartB.style.transform = `translate(${POS_RIGHT}px, 460px)`;
                    cartA.style.transform = `translate(${POS_CENTER}px, 400px)`;
                    await wait(1500);
                }
            }

            // 启动自动播放 (无须用户交互,支持重载即播)
            runCycle();
        });
    </script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分