分享图
动画工坊
引擎就绪
<!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>
    <!-- 引入特殊排版与等宽字体以提升工程美学 -->
    <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Noto+Sans+SC:wght@300;500;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
    <style>
        :root {
            --bg-color: #050505;
            --grid-color: #171717;
            --accent-cyan: #06b6d4;
            --accent-cyan-glow: rgba(6, 182, 212, 0.5);
            --accent-amber: #f59e0b;
            --accent-amber-glow: rgba(245, 158, 11, 0.5);
            --panel-bg: rgba(15, 15, 15, 0.85);
            --text-main: #f8fafc;
            --text-dim: #94a3b8;
            --border-tech: rgba(6, 182, 212, 0.3);
            --font-ui: 'Noto Sans SC', sans-serif;
            --font-data: 'JetBrains Mono', monospace;
            --font-title: 'Orbitron', sans-serif;
        }

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

        body {
            background-color: var(--bg-color);
            color: var(--text-main);
            font-family: var(--font-ui);
            height: 100vh;
            width: 100vw;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            background-image: 
                linear-gradient(rgba(6, 182, 212, 0.03) 1px, transparent 1px),
                linear-gradient(90deg, rgba(6, 182, 212, 0.03) 1px, transparent 1px);
            background-size: 40px 40px;
        }

        .dashboard-container {
            position: relative;
            width: 100%;
            max-width: 1400px;
            height: 100%;
            max-height: 900px;
            display: flex;
            border-radius: 16px;
            box-shadow: 0 0 100px rgba(0, 0, 0, 0.8) inset,
                        0 0 40px rgba(6, 182, 212, 0.1);
            overflow: hidden;
            border: 1px solid #262626;
            background: radial-gradient(circle at center, #111 0%, #000 100%);
        }

        /* 左侧 HUD 界面 */
        .hud-panel {
            position: absolute;
            left: 30px;
            top: 30px;
            width: 320px;
            z-index: 10;
            display: flex;
            flex-direction: column;
            gap: 20px;
            pointer-events: none; /* 让鼠标穿透 */
        }

        .hud-card {
            background: var(--panel-bg);
            border: 1px solid var(--border-tech);
            border-radius: 8px;
            padding: 20px;
            backdrop-filter: blur(10px);
            position: relative;
            overflow: hidden;
        }

        .hud-card::before {
            content: '';
            position: absolute;
            top: 0; left: 0; width: 4px; height: 100%;
            background: var(--accent-cyan);
            box-shadow: 0 0 10px var(--accent-cyan);
        }

        .hud-card.alert::before {
            background: var(--accent-amber);
            box-shadow: 0 0 10px var(--accent-amber);
        }

        .hud-title {
            font-size: 14px;
            color: var(--text-dim);
            letter-spacing: 2px;
            margin-bottom: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .hud-title span.tag {
            font-family: var(--font-title);
            color: var(--accent-cyan);
            font-size: 12px;
            border: 1px solid var(--accent-cyan);
            padding: 2px 6px;
            border-radius: 4px;
        }

        .hud-value {
            font-family: var(--font-data);
            font-size: 28px;
            color: var(--accent-cyan);
            text-shadow: 0 0 15px var(--accent-cyan-glow);
            margin-bottom: 8px;
            display: flex;
            align-items:baseline;
            gap: 5px;
        }
        
        .hud-value.amber {
            color: var(--accent-amber);
            text-shadow: 0 0 15px var(--accent-amber-glow);
        }

        .hud-unit {
            font-size: 14px;
            color: var(--text-dim);
        }

        .hud-desc {
            font-size: 13px;
            line-height: 1.5;
            color: #d1d5db;
        }

        .highlight-text {
            color: var(--accent-cyan);
            font-weight: 700;
        }

        /* 顶部标题 */
        .main-title {
            position: absolute;
            top: 30px;
            left: 50%;
            transform: translateX(-50%);
            text-align: center;
            z-index: 10;
        }

        .main-title h1 {
            font-family: var(--font-title);
            font-size: 24px;
            letter-spacing: 4px;
            text-transform: uppercase;
            color: #fff;
            text-shadow: 0 0 20px rgba(255, 255, 255, 0.5);
            margin-bottom: 8px;
        }

        .main-title h2 {
            font-size: 14px;
            color: var(--text-dim);
            letter-spacing: 6px;
            font-weight: 300;
        }

        /* 右下角交互控制 */
        .controls-panel {
            position: absolute;
            right: 30px;
            bottom: 30px;
            width: 300px;
            background: var(--panel-bg);
            border: 1px solid #333;
            border-radius: 8px;
            padding: 20px;
            z-index: 20;
            backdrop-filter: blur(10px);
        }

        .control-header {
            display: flex;
            justify-content: space-between;
            margin-bottom: 15px;
            font-size: 12px;
            color: var(--text-dim);
            letter-spacing: 1px;
        }

        .slider-container {
            position: relative;
            width: 100%;
            height: 6px;
            background: #262626;
            border-radius: 3px;
        }

        input[type="range"] {
            -webkit-appearance: none;
            width: 100%;
            height: 100%;
            background: transparent;
            position: absolute;
            top: 0;
            left: 0;
            margin: 0;
            cursor: ew-resize;
        }

        input[type="range"]:focus {
            outline: none;
        }

        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 20px;
            width: 20px;
            border-radius: 50%;
            background: var(--accent-cyan);
            cursor: pointer;
            box-shadow: 0 0 15px var(--accent-cyan);
            border: 2px solid #fff;
            transition: transform 0.1s;
        }
        
        input[type="range"]::-webkit-slider-thumb:hover {
            transform: scale(1.2);
        }

        /* 中央可视化区域 */
        .svg-container {
            width: 100%;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        svg {
            width: 100%;
            height: 100%;
            filter: drop-shadow(0 0 20px rgba(0,0,0,0.5));
        }

        /* 动画元素专属样式 */
        .glow-line {
            stroke: var(--accent-cyan);
            stroke-width: 2;
            filter: drop-shadow(0 0 8px var(--accent-cyan));
        }
        
        .carbon-arm {
            stroke: #1f2937;
            stroke-width: 8;
            stroke-linecap: round;
            stroke-linejoin: round;
            transition: stroke 0.3s;
        }
        
        .carbon-arm-inner {
            stroke: #374151;
            stroke-width: 4;
            stroke-linecap: round;
            stroke-linejoin: round;
        }
        
        .pivot-joint {
            fill: #fff;
            stroke: var(--accent-amber);
            stroke-width: 2;
            filter: drop-shadow(0 0 4px var(--accent-amber));
        }

        .lip-glow {
            transition: opacity 0.3s ease, transform 0.3s ease;
        }
    </style>
</head>
<body>

    <div class="dashboard-container">
        <!-- 标题 -->
        <header class="main-title">
            <h1>TRIZ IFR 架构设计</h1>
            <h2>微型碳纤维剪叉隐形遮阳系统</h2>
        </header>

        <!-- 左侧数据分析板 -->
        <aside class="hud-panel">
            <div class="hud-card">
                <div class="hud-title">核心原理 <span class="tag">IFR</span></div>
                <div class="hud-desc">
                    最终理想解(IFR)旨在不引入复杂组件的前提下消除矛盾。本系统采用极薄碳纤维机械臂穿透自闭合磁性硅胶唇边,实现<span class="highlight-text">结构收纳隐形</span>与<span class="highlight-text">内饰外观无孔洞</span>的完美统一。
                </div>
            </div>

            <div class="hud-card alert" id="card-gap">
                <div class="hud-title">硅胶唇边磁力状态 <span class="tag">STATUS</span></div>
                <div class="hud-value amber" id="val-force">2.0 <span class="hud-unit">N</span></div>
                <div class="hud-desc">状态: <span id="status-text" class="highlight-text" style="color:var(--accent-amber)">完全吸合 (无缝隙)</span></div>
                <div class="hud-desc" style="margin-top: 5px; font-size:11px; opacity:0.7">磁吸硅胶条在常态下保持强力闭合,阻隔灰尘并维持内饰完整性。</div>
            </div>

            <div class="hud-card" id="card-arm">
                <div class="hud-title">剪叉臂厚度 <span class="tag">PHYSICS</span></div>
                <div class="hud-value">8.0 <span class="hud-unit">mm</span></div>
                <div class="hud-desc">利用多级铝合金与碳纤维复合冲压工艺,将机械臂厚度压缩至极致,穿刺时两侧仍维持磁力吸合。</div>
            </div>
        </aside>

        <!-- 右下角手动交互 -->
        <div class="controls-panel">
            <div class="control-header">
                <span>动态演示控制 (AUTO)</span>
                <span id="progress-percent">0%</span>
            </div>
            <div class="slider-container">
                <input type="range" id="manual-slider" min="0" max="100" value="0">
            </div>
            <div style="font-size: 11px; color: #64748b; margin-top: 12px; text-align: center;">
                拖动滑块可手动探索理想解机理<br>释放2秒后自动恢复运行
            </div>
        </div>

        <!-- 核心SVG画布 -->
        <main class="svg-container">
            <svg id="mechanism" viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet">
                <defs>
                    <!-- 渐变与滤镜 -->
                    <linearGradient id="shade-grad" x1="0%" y1="0%" x2="0%" y2="100%">
                        <stop offset="0%" stop-color="rgba(6, 182, 212, 0.4)" />
                        <stop offset="100%" stop-color="rgba(6, 182, 212, 0.05)" />
                    </linearGradient>
                    
                    <linearGradient id="lip-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                        <stop offset="0%" stop-color="#1e293b" />
                        <stop offset="45%" stop-color="#334155" />
                        <stop offset="50%" stop-color="#06b6d4" />
                        <stop offset="55%" stop-color="#334155" />
                        <stop offset="100%" stop-color="#1e293b" />
                    </linearGradient>

                    <radialGradient id="motor-glow" cx="50%" cy="50%" r="50%">
                        <stop offset="0%" stop-color="rgba(245, 158, 11, 0.8)"/>
                        <stop offset="100%" stop-color="rgba(245, 158, 11, 0)"/>
                    </radialGradient>

                    <filter id="glow">
                        <feGaussianBlur stdDeviation="4" result="coloredBlur"/>
                        <feMerge>
                            <feMergeNode in="coloredBlur"/>
                            <feMergeNode in="SourceGraphic"/>
                        </feMerge>
                    </filter>
                    
                    <!-- 碳纤维纹理 -->
                    <pattern id="carbon" width="4" height="4" patternUnits="userSpaceOnUse">
                        <rect width="4" height="4" fill="#171717"/>
                        <path d="M0,4 l4,-4" stroke="#262626" stroke-width="1"/>
                    </pattern>

                    <clipPath id="zoom-clip">
                        <circle cx="950" cy="250" r="120" />
                    </clipPath>
                </defs>

                <!-- 背景导视线段 -->
                <g stroke="#1e293b" stroke-width="1" stroke-dasharray="4 4">
                    <line x1="600" y1="50" x2="600" y2="750" />
                    <line x1="200" y1="550" x2="1000" y2="550" />
                </g>

                <!-- 车窗边框 (平行四边形变体) -->
                <path d="M 350,150 L 850,150 L 950,500 L 250,500 Z" 
                      fill="none" stroke="#334155" stroke-width="6" stroke-linejoin="round" />
                <path d="M 350,150 L 850,150 L 950,500 L 250,500 Z" 
                      fill="none" stroke="#000" stroke-width="2" stroke-linejoin="round" />

                <!-- 遮阳帘布 -->
                <polygon id="shade-cloth" points="250,500 950,500 950,500 250,500" 
                         fill="url(#shade-grad)" stroke="var(--accent-cyan)" stroke-width="1" />

                <!-- 磁性硅胶唇边 (门板饰条位置 Y=500) -->
                <rect x="200" y="495" width="800" height="10" rx="5" fill="#111827" stroke="#334155" stroke-width="2"/>
                <!-- 唇边发光指示 -->
                <path id="magnetic-lip-glow" d="M 200,500 L 1000,500" 
                      stroke="url(#lip-grad)" stroke-width="3" filter="url(#glow)" class="lip-glow"/>
                <circle id="puncture-point" cx="600" cy="500" r="0" fill="none" stroke="var(--accent-cyan)" stroke-width="2" filter="url(#glow)"/>

                <!-- 牵引杆 -->
                <line id="traction-bar" x1="250" y1="500" x2="950" y2="500" 
                      stroke="#94a3b8" stroke-width="6" stroke-linecap="round" />

                <!-- 剪叉机械臂组 -->
                <g id="scissor-group">
                    <!-- 通过 JS 动态生成连杆 -->
                </g>

                <!-- 底部驱动机构 (Y=620) -->
                <g id="drive-system" transform="translate(0, 620)">
                    <!-- 丝杠 -->
                    <rect x="350" y="-5" width="500" height="10" fill="#334155" />
                    <!-- 丝杠螺纹效果 -->
                    <path d="M 350, -5 L 850, 5 M 355, -5 L 855, 5" stroke="#1e293b" stroke-width="2" stroke-dasharray="2 4"/>
                    
                    <!-- 电机 -->
                    <circle cx="330" cy="0" r="30" fill="url(#motor-glow)" />
                    <rect x="290" y="-20" width="60" height="40" rx="4" fill="#1f2937" stroke="#f59e0b" stroke-width="2"/>
                    <g id="motor-rotor">
                        <circle cx="350" cy="0" r="12" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
                        <line x1="338" y1="0" x2="362" y2="0" stroke="#f59e0b" stroke-width="2"/>
                        <line x1="350" y1="-12" x2="350" y2="12" stroke="#f59e0b" stroke-width="2"/>
                    </g>
                    <text x="290" y="35" font-size="10" fill="var(--accent-amber)" font-family="var(--font-data)">STEP MOTOR</text>
                    
                    <!-- 滑块 -->
                    <rect id="block-l" x="400" y="-10" width="30" height="20" rx="3" fill="#06b6d4" />
                    <rect id="block-r" x="770" y="-10" width="30" height="20" rx="3" fill="#06b6d4" />
                </g>

                <!-- 顶部微观剖面放大镜 (Inset View) -->
                <g transform="translate(0, 0)">
                    <circle cx="950" cy="250" r="125" fill="#050505" stroke="#334155" stroke-width="4"/>
                    <circle cx="950" cy="250" r="120" fill="#0b1120"/>
                    
                    <g clip-path="url(#zoom-clip)">
                        <!-- 背景网格 -->
                        <g stroke="#1e293b" stroke-width="1" stroke-dasharray="2 2">
                            <line x1="830" y1="250" x2="1070" y2="250" />
                            <line x1="950" y1="130" x2="950" y2="370" />
                        </g>

                        <!-- 硅胶唇边左/右 -->
                        <path id="zoom-lip-l" d="M 830,220 C 900,220 940,230 940,250 C 940,270 900,280 830,280 Z" fill="rgba(6, 182, 212, 0.2)" stroke="#06b6d4" stroke-width="2"/>
                        <path id="zoom-lip-r" d="M 1070,220 C 1000,220 960,230 960,250 C 960,270 1000,280 1070,280 Z" fill="rgba(6, 182, 212, 0.2)" stroke="#06b6d4" stroke-width="2"/>

                        <!-- 磁力线示意 -->
                        <g id="zoom-magnetic-waves" stroke="var(--accent-cyan)" stroke-dasharray="4 4" opacity="0.8">
                            <path d="M 942,240 Q 950,230 958,240" fill="none"/>
                            <path d="M 942,250 L 958,250" fill="none"/>
                            <path d="M 942,260 Q 950,270 958,260" fill="none"/>
                        </g>

                        <!-- 穿刺碳纤维臂剖面 -->
                        <rect id="zoom-arm" x="946" y="290" width="8" height="100" rx="4" fill="url(#carbon)" stroke="#94a3b8" stroke-width="2" opacity="0"/>
                        <circle id="zoom-arm-joint" cx="950" cy="340" r="3" fill="#f59e0b" opacity="0"/>
                    </g>
                    
                    <!-- 放大镜UI边框装饰 -->
                    <path d="M 825,250 A 125 125 0 0 1 1075,250" fill="none" stroke="var(--accent-cyan)" stroke-width="2" stroke-dasharray="10 15"/>
                    <text x="950" y="115" text-anchor="middle" font-size="12" fill="var(--accent-cyan)" font-family="var(--font-title)">MICRO-CROSS-SECTION</text>
                    <text x="950" y="395" text-anchor="middle" font-size="12" fill="#94a3b8">磁性闭合力 / 8mm微间隙</text>
                    
                    <!-- 连接线 -->
                    <path id="zoom-pointer" d="M 600,500 L 850,320" fill="none" stroke="#334155" stroke-width="1" stroke-dasharray="4 4"/>
                    <circle cx="850" cy="320" r="3" fill="var(--accent-cyan)"/>
                </g>
            </svg>
        </main>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const CONFIG = {
                centerX: 600,
                baseY: 620,
                targetY_min: 500, // 隐藏状态顶部高度
                targetY_max: 150, // 展开状态顶部高度
                stages: 4,        // 剪叉级数
                linkHalfLength: 90, // 单根连杆半长
            };

            // DOM 元素
            const elements = {
                scissorGroup: document.getElementById('scissor-group'),
                shadeCloth: document.getElementById('shade-cloth'),
                tractionBar: document.getElementById('traction-bar'),
                blockL: document.getElementById('block-l'),
                blockR: document.getElementById('block-r'),
                motorRotor: document.getElementById('motor-rotor'),
                progressPercent: document.getElementById('progress-percent'),
                slider: document.getElementById('manual-slider'),
                valForce: document.getElementById('val-force'),
                statusText: document.getElementById('status-text'),
                cardGap: document.getElementById('card-gap'),
                puncturePoint: document.getElementById('puncture-point'),
                zoomLipL: document.getElementById('zoom-lip-l'),
                zoomLipR: document.getElementById('zoom-lip-r'),
                zoomArm: document.getElementById('zoom-arm'),
                zoomJoint: document.getElementById('zoom-arm-joint'),
                zoomMagWaves: document.getElementById('zoom-magnetic-waves'),
                zoomPointer: document.getElementById('zoom-pointer')
            };

            // 状态变量
            let progress = 0; // 0 到 1
            let isPlaying = true;
            let direction = 1;
            let animationFrameId = null;
            let pauseTimeout = null;

            // 初始化剪叉 SVG 结构
            const links = [];
            const joints = [];
            
            function initSVG() {
                // 每级有两个交叉杆: / 和 \
                for (let i = 0; i < CONFIG.stages; i++) {
                    // /
                    const line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    line1.setAttribute('class', 'carbon-arm');
                    
                    const inner1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    inner1.setAttribute('class', 'carbon-arm-inner');
                    
                    // \
                    const line2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    line2.setAttribute('class', 'carbon-arm');
                    
                    const inner2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                    inner2.setAttribute('class', 'carbon-arm-inner');

                    elements.scissorGroup.appendChild(line1);
                    elements.scissorGroup.appendChild(line2);
                    elements.scissorGroup.appendChild(inner1);
                    elements.scissorGroup.appendChild(inner2);

                    links.push({ out: line1, in: inner1, type: 'slash' });
                    links.push({ out: line2, in: inner2, type: 'backslash' });

                    // 中间铰链与两端铰链
                    const jointM = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
                    jointM.setAttribute('class', 'pivot-joint');
                    jointM.setAttribute('r', '4');
                    elements.scissorGroup.appendChild(jointM);
                    joints.push(jointM);
                    
                    // 底部铰链 (仅在第一级和连接处需要)
                    const jointL = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
                    jointL.setAttribute('class', 'pivot-joint');
                    jointL.setAttribute('r', '4');
                    elements.scissorGroup.appendChild(jointL);
                    joints.push(jointL);
                    
                    const jointR = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
                    jointR.setAttribute('class', 'pivot-joint');
                    jointR.setAttribute('r', '4');
                    elements.scissorGroup.appendChild(jointR);
                    joints.push(jointR);
                }
            }

            // 渲染一帧
            function render(p) {
                // 1. 计算剪叉学参数
                // p=0 时,高度 H_min = (baseY - targetY_min)
                // p=1 时,高度 H_max = (baseY - targetY_max)
                const currentY_top = CONFIG.targetY_min - p * (CONFIG.targetY_min - CONFIG.targetY_max);
                const totalHeight = CONFIG.baseY - currentY_top;
                
                // 每级的高度 2h = totalHeight / stages
                const h = totalHeight / (2 * CONFIG.stages);
                
                // 半宽 W = sqrt(L^2 - h^2)
                const L = CONFIG.linkHalfLength;
                const W = Math.sqrt(L * L - h * h);
                
                const xl = CONFIG.centerX - W;
                const xr = CONFIG.centerX + W;

                // 2. 更新滑块位置
                elements.blockL.setAttribute('x', xl - 15);
                elements.blockR.setAttribute('x', xr - 15);

                // 3. 更新电机旋转
                const rot = p * 1440; // 旋转 4 圈
                elements.motorRotor.setAttribute('transform', `rotate(${rot}, 350, 0)`);

                // 4. 更新连杆与铰链
                let jointIdx = 0;
                for (let i = 0; i < CONFIG.stages; i++) {
                    const y_bottom = CONFIG.baseY - i * 2 * h;
                    const y_top = CONFIG.baseY - (i + 1) * 2 * h;
                    const y_mid = CONFIG.baseY - i * 2 * h - h;

                    const linkIdx = i * 2;
                    // / slash link: Left-Bottom to Right-Top
                    links[linkIdx].out.setAttribute('x1', xl); links[linkIdx].out.setAttribute('y1', y_bottom);
                    links[linkIdx].out.setAttribute('x2', xr); links[linkIdx].out.setAttribute('y2', y_top);
                    links[linkIdx].in.setAttribute('x1', xl);  links[linkIdx].in.setAttribute('y1', y_bottom);
                    links[linkIdx].in.setAttribute('x2', xr);  links[linkIdx].in.setAttribute('y2', y_top);

                    // \ backslash link: Right-Bottom to Left-Top
                    links[linkIdx+1].out.setAttribute('x1', xr); links[linkIdx+1].out.setAttribute('y1', y_bottom);
                    links[linkIdx+1].out.setAttribute('x2', xl); links[linkIdx+1].out.setAttribute('y2', y_top);
                    links[linkIdx+1].in.setAttribute('x1', xr);  links[linkIdx+1].in.setAttribute('y1', y_bottom);
                    links[linkIdx+1].in.setAttribute('x2', xl);  links[linkIdx+1].in.setAttribute('y2', y_top);

                    // Joints
                    joints[jointIdx].setAttribute('cx', CONFIG.centerX); joints[jointIdx].setAttribute('cy', y_mid); jointIdx++;
                    joints[jointIdx].setAttribute('cx', xl); joints[jointIdx].setAttribute('cy', y_bottom); jointIdx++;
                    joints[jointIdx].setAttribute('cx', xr); joints[jointIdx].setAttribute('cy', y_bottom); jointIdx++;
                }

                // 5. 更新顶部牵引杆与遮阳帘形状 (受平行四边形车窗约束)
                // 车窗左边缘: 250,500 到 350,150 -> dx/dy = 100 / -350
                // 车窗右边缘: 950,500 到 850,150 -> dx/dy = -100 / -350
                const dy = currentY_top - 500;
                const leftX = 250 + dy * (100 / -350);
                const rightX = 950 + dy * (-100 / -350);
                
                elements.tractionBar.setAttribute('y1', currentY_top);
                elements.tractionBar.setAttribute('y2', currentY_top);
                elements.tractionBar.setAttribute('x1', leftX);
                elements.tractionBar.setAttribute('x2', rightX);

                elements.shadeCloth.setAttribute('points', `250,500 950,500 ${rightX},${currentY_top} ${leftX},${currentY_top}`);

                // 6. 更新 IFR 核心表现 (唇边突破与闭合)
                updateMicroSection(p, currentY_top);
                
                // 7. 更新UI百分比
                elements.progressPercent.textContent = `${(p * 100).toFixed(0)}%`;
                elements.slider.value = p * 100;
            }

            function updateMicroSection(p, y_top) {
                // 缝隙磁力计算
                // 当剪叉最顶部 y_top < 500 且 仍在伸出过程中,说明机械臂正穿过缝隙。
                // 实际上由于是 X 型交叉,中心点(600)始终有一根碳纤维杆在上下滑动。
                // 只要 p > 0.02,臂就穿过了缝隙。
                const isPenetrating = p > 0.05;
                
                if (isPenetrating) {
                    // 吸力受阻,微观打开
                    elements.zoomLipL.setAttribute('d', 'M 830,220 C 900,220 934,230 934,250 C 934,270 900,280 830,280 Z');
                    elements.zoomLipR.setAttribute('d', 'M 1070,220 C 1000,220 966,230 966,250 C 966,270 1000,280 1070,280 Z');
                    elements.zoomMagWaves.style.opacity = '0.2';
                    elements.zoomMagWaves.setAttribute('stroke', '#ef4444'); // 磁力波变红减弱
                    
                    // 碳纤维臂出现
                    elements.zoomArm.style.opacity = '1';
                    elements.zoomJoint.style.opacity = '1';
                    
                    // 将手臂的移动映射到局部放大区
                    // 用一个相对运动模拟
                    const localY = 250 + ((p * 1000) % 60) - 30; 
                    elements.zoomArm.setAttribute('y', localY - 50);
                    elements.zoomJoint.setAttribute('cy', localY);
                    
                    // HUD 状态更新
                    elements.valForce.textContent = '1.5';
                    elements.valForce.className = 'hud-value';
                    elements.statusText.textContent = '极薄穿透 (两侧吸合)';
                    elements.statusText.style.color = 'var(--accent-cyan)';
                    elements.cardGap.classList.remove('alert');

                    // 主视图穿刺点发光
                    elements.puncturePoint.setAttribute('r', 12 + Math.sin(p * 20) * 4);
                    elements.puncturePoint.style.opacity = '1';
                    
                    // 连线指向穿刺点
                    elements.zoomPointer.setAttribute('d', 'M 600,500 L 850,320');
                } else {
                    // 完全闭合
                    elements.zoomLipL.setAttribute('d', 'M 830,220 C 900,220 940,230 940,250 C 940,270 900,280 830,280 Z');
                    elements.zoomLipR.setAttribute('d', 'M 1070,220 C 1000,220 960,230 960,250 C 960,270 1000,280 1070,280 Z');
                    elements.zoomMagWaves.style.opacity = '0.8';
                    elements.zoomMagWaves.setAttribute('stroke', 'var(--accent-cyan)');
                    
                    elements.zoomArm.style.opacity = '0';
                    elements.zoomJoint.style.opacity = '0';
                    
                    elements.valForce.textContent = '2.0';
                    elements.valForce.className = 'hud-value amber';
                    elements.statusText.textContent = '瞬间自动闭合 (无缝)';
                    elements.statusText.style.color = 'var(--accent-amber)';
                    elements.cardGap.classList.add('alert');

                    elements.puncturePoint.style.opacity = '0';
                    elements.zoomPointer.setAttribute('d', 'M 600,500 L 850,320'); // 虚线连接
                }
            }

            // 动画循环
            let lastTime = 0;
            const SPEED = 0.0003; // 动画速度
            
            function animate(time) {
                if (!lastTime) lastTime = time;
                const deltaTime = time - lastTime;
                lastTime = time;

                if (isPlaying) {
                    if (direction === 1) {
                        progress += SPEED * deltaTime;
                        if (progress >= 1) {
                            progress = 1;
                            direction = -1;
                            isPlaying = false;
                            setTimeout(() => { isPlaying = true; }, 2000); // 顶部停留 2 秒
                        }
                    } else {
                        progress -= SPEED * deltaTime;
                        if (progress <= 0) {
                            progress = 0;
                            direction = 1;
                            isPlaying = false;
                            setTimeout(() => { isPlaying = true; }, 2000); // 底部停留 2 秒
                        }
                    }
                    render(progress);
                }

                animationFrameId = requestAnimationFrame(animate);
            }

            // 交互控制
            elements.slider.addEventListener('input', (e) => {
                isPlaying = false;
                progress = e.target.value / 100;
                render(progress);
                clearTimeout(pauseTimeout);
            });

            elements.slider.addEventListener('change', () => {
                // 释放后 2 秒恢复自动播放
                clearTimeout(pauseTimeout);
                pauseTimeout = setTimeout(() => {
                    lastTime = 0; // 重置计时器防止跳变
                    isPlaying = true;
                    // 确定运动方向
                    direction = progress >= 0.5 ? -1 : 1; 
                }, 2000);
            });

            // 启动初始化
            initSVG();
            render(0);
            
            // 满足 "重开即播 / 加载后自动播放" 需求
            animationFrameId = requestAnimationFrame(animate);
        });
    </script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分