分享图
动画工坊
引擎就绪
<!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>
        @import url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap');

        :root {
            --bg-color: #030712;
            --grid-color: rgba(30, 41, 59, 0.5);
            --cyan-glow: #00f0ff;
            --cyan-dim: rgba(0, 240, 255, 0.15);
            --neon-pink: #ff2a6d;
            --neon-orange: #ff9f1c;
            --neon-green: #05ffa1;
            --text-main: #f8fafc;
            --text-muted: #94a3b8;
            --panel-bg: rgba(15, 23, 42, 0.7);
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                linear-gradient(var(--grid-color) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
            background-size: 40px 40px;
            font-family: 'Noto Sans SC', sans-serif;
            color: var(--text-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        /* 径向暗角渐变增加深度 */
        .vignette {
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            background: radial-gradient(circle at 50% 50%, transparent 20%, #030712 100%);
            pointer-events: none;
            z-index: 0;
        }

        #animation-container {
            position: relative;
            width: 100vw;
            height: 100vh;
            max-width: 1600px;
            max-height: 900px;
            z-index: 1;
            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));
        }

        /* UI 面板与数据展示 */
        .hud-panel {
            position: absolute;
            background: var(--panel-bg);
            border: 1px solid rgba(0, 240, 255, 0.2);
            backdrop-filter: blur(10px);
            padding: 24px;
            border-radius: 8px;
            box-shadow: 0 0 30px rgba(0, 0, 0, 0.6), inset 0 0 20px rgba(0, 240, 255, 0.05);
            pointer-events: none;
        }
        
        .hud-panel::before {
            content: '';
            position: absolute;
            top: -1px; left: -1px;
            width: 20px; height: 20px;
            border-top: 2px solid var(--cyan-glow);
            border-left: 2px solid var(--cyan-glow);
        }
        
        .hud-panel::after {
            content: '';
            position: absolute;
            bottom: -1px; right: -1px;
            width: 20px; height: 20px;
            border-bottom: 2px solid var(--cyan-glow);
            border-right: 2px solid var(--cyan-glow);
        }

        #panel-ifr {
            top: 40px;
            left: 40px;
            width: 320px;
        }

        #panel-status {
            bottom: 40px;
            right: 40px;
            width: 360px;
        }

        h2 {
            font-family: 'Chakra Petch', sans-serif;
            font-size: 24px;
            margin: 0 0 16px 0;
            color: var(--cyan-glow);
            letter-spacing: 2px;
            text-transform: uppercase;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        h2::before {
            content: '';
            display: inline-block;
            width: 8px;
            height: 24px;
            background: var(--cyan-glow);
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 12px;
            font-size: 14px;
            border-bottom: 1px dashed rgba(255,255,255,0.1);
            padding-bottom: 4px;
        }

        .data-row .label {
            color: var(--text-muted);
        }

        .data-row .value {
            font-family: 'Chakra Petch', sans-serif;
            font-weight: 600;
            color: var(--neon-green);
        }

        .data-row .value.warning {
            color: var(--neon-pink);
            text-shadow: 0 0 10px rgba(255, 42, 109, 0.8);
            animation: pulse 0.5s infinite alternate;
        }

        .ifr-concept {
            margin-top: 20px;
        }

        .ifr-item {
            margin-bottom: 16px;
            padding-left: 12px;
            border-left: 2px solid var(--neon-orange);
        }
        
        .ifr-item:nth-child(2) { border-left-color: var(--cyan-glow); }

        .ifr-item .title {
            font-weight: 700;
            font-size: 15px;
            margin-bottom: 4px;
            color: #fff;
        }

        .ifr-item .desc {
            font-size: 13px;
            color: var(--text-muted);
            line-height: 1.5;
        }

        @keyframes pulse {
            from { opacity: 0.8; }
            to { opacity: 1; transform: scale(1.02); }
        }

        .glowing-text {
            font-family: 'Chakra Petch', sans-serif;
            font-weight: 700;
        }
    </style>
</head>
<body>

    <div class="vignette"></div>

    <div id="animation-container">
        <!-- SVG Canvas -->
        <svg id="main-svg" viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <!-- Filters for glowing effects -->
                <filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="6" result="blur" />
                    <feMerge>
                        <feMergeNode in="blur" />
                        <feMergeNode in="blur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>

                <filter id="glow-orange" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="5" result="blur" />
                    <feComponentTransfer in="blur" result="glow">
                        <feFuncA type="linear" slope="2"/>
                    </feComponentTransfer>
                    <feMerge>
                        <feMergeNode in="glow" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>

                <filter id="glow-red" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="8" result="blur" />
                    <feMerge>
                        <feMergeNode in="blur" />
                        <feMergeNode in="SourceGraphic" />
                    </feMerge>
                </filter>

                <!-- Gradients -->
                <linearGradient id="glass-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="rgba(0, 240, 255, 0.02)" />
                    <stop offset="80%" stop-color="rgba(0, 240, 255, 0.08)" />
                    <stop offset="100%" stop-color="rgba(0, 240, 255, 0.3)" />
                </linearGradient>

                <linearGradient id="metal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" stop-color="#1e293b" />
                    <stop offset="50%" stop-color="#334155" />
                    <stop offset="100%" stop-color="#0f172a" />
                </linearGradient>
            </defs>

            <!-- BACKGROUND & ENVIRONMENT -->
            <g id="environment">
                <!-- Car Door Framework -->
                <path d="M 680 750 L 680 400 Q 680 380 660 380 L 600 380 L 600 750 Z" fill="url(#metal-grad)" stroke="#475569" stroke-width="2"/>
                <path d="M 600 450 L 580 430 L 580 750 L 600 750 Z" fill="#0f172a" stroke="#334155" stroke-width="1"/>
                
                <!-- Glass Panel (Y-axis Support) -->
                <rect x="420" y="50" width="15" height="700" fill="url(#glass-grad)" stroke="rgba(0,240,255,0.5)" stroke-width="1"/>
                <line x1="435" y1="50" x2="435" y2="750" stroke="#00f0ff" stroke-width="3" filter="url(#glow-cyan)"/>
                
                <!-- Coordinate / Technical markers -->
                <text x="400" y="40" fill="#00f0ff" font-family="Chakra Petch" font-size="12" text-anchor="end" opacity="0.8">Y-AXIS (GLASS SUPPORT)</text>
                <path d="M 405 50 L 415 50 L 415 750 L 405 750" fill="none" stroke="#00f0ff" stroke-width="1" opacity="0.5"/>
            </g>

            <!-- MECHANISM COMPONENTS -->
            
            <!-- 1. Split Base System -->
            <g id="base-system">
                <!-- 3M VHB Tape & Steel Plate (Glued to door) -->
                <!-- Door is at X=580. Plate is attached to door surface -->
                <rect id="plate-3m" x="570" y="500" width="10" height="80" fill="#ff9f1c" rx="2" filter="url(#glow-orange)"/>
                
                <!-- Main Magnetic Base (Detachable) -->
                <g id="magnet-base">
                    <!-- Base body -->
                    <rect id="base-body" x="535" y="490" width="35" height="100" fill="#1e293b" stroke="#00f0ff" stroke-width="1.5" rx="4"/>
                    <!-- Magnet contact surface (Red/Magenta to indicate magnetic lock) -->
                    <rect id="magnet-lock" x="565" y="500" width="5" height="80" fill="#ff2a6d" />
                    <!-- Hinge / connection point for the arm -->
                    <circle cx="545" cy="540" r="5" fill="#00f0ff" filter="url(#glow-cyan)"/>
                    <circle cx="545" cy="540" r="2" fill="#fff" />
                    
                    <!-- Magnetic Field Lines (Visible when attached) -->
                    <g id="mag-fields" stroke="#ff2a6d" stroke-width="1" opacity="0.6" stroke-dasharray="2 2">
                        <line x1="570" y1="510" x2="585" y2="510" />
                        <line x1="570" y1="540" x2="585" y2="540" />
                        <line x1="570" y1="570" x2="585" y2="570" />
                    </g>
                </g>
            </g>

            <!-- 2. The Thin Spring Arm (Dynamic Path) -->
            <!-- Start at Base (545, 540), End at Slider -->
            <path id="spring-arm" d="M 545 540 Q 480 500 450 600" fill="none" stroke="#e2e8f0" stroke-width="2" stroke-linecap="round"/>
            <!-- Glow effect to show stress -->
            <path id="spring-arm-stress" d="M 545 540 Q 480 500 450 600" fill="none" stroke="#ff2a6d" stroke-width="6" stroke-linecap="round" opacity="0" filter="url(#glow-red)"/>

            <!-- 3. Top Slider Assembly -->
            <g id="slider-assembly">
                <!-- PTFE / Teflon Slider touching the glass (X=435) -->
                <rect id="teflon-slider" x="435" y="580" width="15" height="40" fill="#05ffa1" rx="4" filter="url(#glow-cyan)"/>
                <!-- Connecting rod/bracket -->
                <path d="M 450 590 L 460 590 L 460 610 L 450 610 Z" fill="#475569" />
                <circle cx="455" cy="600" r="4" fill="#00f0ff" />
                <!-- Interaction spark/glow when moving -->
                <ellipse id="friction-spark" cx="435" cy="600" rx="4" ry="15" fill="#ffffff" opacity="0.8" filter="url(#glow-cyan)"/>
            </g>

            <!-- 4. Obstacle / Jam Simulator -->
            <g id="jam-block" opacity="0">
                <rect x="420" y="250" width="60" height="30" fill="#ff2a6d" rx="4" filter="url(#glow-red)"/>
                <path d="M 420 250 L 480 280 L 420 280 Z" fill="rgba(0,0,0,0.3)"/> <!-- Shading -->
                <text x="450" y="270" fill="white" font-family="Noto Sans SC" font-weight="700" font-size="14" text-anchor="middle" dominant-baseline="middle">卡滞异物</text>
            </g>

            <!-- DYNAMIC HUD ANNOTATIONS IN SVG -->
            <!-- Base connection line -->
            <path id="anno-line-base" d="M 535 540 L 450 540 L 430 450 L 320 450" fill="none" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4 2"/>
            <text id="anno-text-base" x="310" y="445" fill="#ff9f1c" font-size="14" text-anchor="end" class="glowing-text">磁吸主体 (过载释放点)</text>
            
            <!-- Arm connection line -->
            <path id="anno-line-arm" d="M 480 400 L 400 400 L 380 350 L 320 350" fill="none" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4 2"/>
            <text x="310" y="345" fill="#e2e8f0" font-size="14" text-anchor="end" class="glowing-text">1.5mm极薄高强弹簧钢板</text>
            <text x="310" y="365" fill="#94a3b8" font-size="12" text-anchor="end">无Y向承载,厚度趋近于0</text>

            <!-- Slider connection line -->
            <path id="anno-line-slider" d="M 435 600 L 350 600 L 330 650 L 320 650" fill="none" stroke="#94a3b8" stroke-width="1" stroke-dasharray="4 2"/>
            <text id="anno-text-slider" x="310" y="645" fill="#05ffa1" font-size="14" text-anchor="end" class="glowing-text">特氟龙(PTFE)柔性滑块</text>
            <text x="310" y="665" fill="#94a3b8" font-size="12" text-anchor="end">借用玻璃刚度,摩擦系数 <0.05</text>

            <!-- Force Vector Arrows -->
            <g id="force-vectors">
                <!-- Z-Axis Lift Force -->
                <path id="arrow-z" d="M 465 620 L 465 660 M 460 625 L 465 620 L 470 625" fill="none" stroke="#00f0ff" stroke-width="2"/>
                <text id="text-force-z" x="475" y="645" fill="#00f0ff" font-family="Chakra Petch" font-size="14" font-weight="bold">Fz</text>
                
                <!-- Y-Axis Support Force (Glass pushing back) -->
                <path id="arrow-y" d="M 410 600 L 430 600 M 425 595 L 430 600 L 425 605" fill="none" stroke="#05ffa1" stroke-width="2" opacity="0.8"/>
                <text x="390" y="605" fill="#05ffa1" font-family="Chakra Petch" font-size="14" font-weight="bold">Fy</text>
            </g>

        </svg>
    </div>

    <!-- UI Overlay / HUD Panels -->
    <div class="hud-panel" id="panel-ifr">
        <h2>最终理想解 [IFR]</h2>
        <div class="ifr-concept">
            <div class="ifr-item">
                <div class="title">1. 彻底消除悬臂受力</div>
                <div class="desc">放弃曲臂“悬空硬抗”,转而利用<strong>原车玻璃作为Y向支撑面</strong>。曲臂仅提供Z向推力,实现极薄厚度与0间隙收纳。</div>
            </div>
            <div class="ifr-item">
                <div class="title">2. 巧妙引入磁力保护</div>
                <div class="desc">放弃强化3M胶,利用<strong>分体式磁吸底座</strong>作为可重复安装的过载释放机制。受阻时主动断开,保护系统。</div>
            </div>
        </div>
    </div>

    <div class="hud-panel" id="panel-status">
        <h2>系统遥测 [TELEMETRY]</h2>
        <div class="data-row">
            <span class="label">当前运行阶段:</span>
            <span class="value" id="ui-phase">系统初始化</span>
        </div>
        <div class="data-row">
            <span class="label">电机输出推力 (Fz):</span>
            <span class="value" id="ui-force">0.0 N</span>
        </div>
        <div class="data-row">
            <span class="label">滑块接触面摩擦系数:</span>
            <span class="value" style="color:var(--neon-green)">μ = 0.042</span>
        </div>
        <div class="data-row">
            <span class="label">磁吸锁止状态:</span>
            <span class="value" id="ui-magnet-status">吸附稳定 [🔒]</span>
        </div>
        <div class="data-row">
            <span class="label">安全阈值 / 防夹力:</span>
            <span class="value" style="color:var(--text-muted)">50.0 N / 60.0 N</span>
        </div>
    </div>

    <script>
        /**
         * 柔性曲臂与磁吸过载保护 - 动画核心逻辑
         * 采用 RequestAnimationFrame 实现精确的物理与状态同步控制
         */
        
        // --- 核心 DOM 元素 ---
        const els = {
            slider: document.getElementById('slider-assembly'),
            arm: document.getElementById('spring-arm'),
            armStress: document.getElementById('spring-arm-stress'),
            magnetBase: document.getElementById('magnet-base'),
            magFields: document.getElementById('mag-fields'),
            jamBlock: document.getElementById('jam-block'),
            frictionSpark: document.getElementById('friction-spark'),
            arrowZ: document.getElementById('arrow-z'),
            
            // 动态标注线
            lineSlider: document.getElementById('anno-line-slider'),
            textSlider: document.getElementById('anno-text-slider'),
            lineArm: document.getElementById('anno-line-arm'),
            
            // UI 更新
            uiPhase: document.getElementById('ui-phase'),
            uiForce: document.getElementById('ui-force'),
            uiMagnetStatus: document.getElementById('ui-magnet-status')
        };

        // --- 坐标与物理常量 ---
        const config = {
            baseStaticX: 545,  // 磁吸底座连接点基准X
            baseStaticY: 540,  // 磁吸底座连接点基准Y
            plateX: 570,       // 3M胶板表面X
            sliderStrokeMin: 580, // 滑块最底部 Y
            sliderStrokeMax: 100, // 滑块最顶部 Y
            jamY: 250,         // 卡滞物底部 Y
            magThreshold: 50,  // 磁吸断开阈值 N
        };

        // --- 时间轴关键帧定义 (无限循环剧本) ---
        // 剧本总时长:约 14 秒
        const timeline = [
            { t: 0,     state: 'IDLE',   desc: '待机状态', targetY: 580, jamOpacity: 0, force: 0 },
            { t: 1000,  state: 'UP',     desc: '正常升起 - 玻璃Y向支撑', targetY: 100, jamOpacity: 0, force: 15 },
            { t: 4000,  state: 'DOWN',   desc: '平滑收纳 - 极薄曲臂0间隙', targetY: 580, jamOpacity: 0, force: 10 },
            { t: 7000,  state: 'IDLE',   desc: '遭遇极端工况 / 异物入侵', targetY: 580, jamOpacity: 1, force: 0 },
            { t: 8000,  state: 'JAM_UP', desc: '升降启动', targetY: 250, jamOpacity: 1, force: 15 }, // 上升到碰触卡滞物
            { t: 9500,  state: 'JAMMED', desc: '系统卡滞 - 应力急剧上升', targetY: 250, jamOpacity: 1, force: 65 }, // 电机继续推,推力飙升超过50
            { t: 11000, state: 'RELEASE',desc: '过载卸力 - 磁吸主动脱落', targetY: 250, jamOpacity: 1, force: 0 }, // 超过50N后脱落,拉力归零
            { t: 13500, state: 'RESET',  desc: '系统复位', targetY: 580, jamOpacity: 0, force: 0 },
            { t: 14000, state: 'END',    desc: '循环', targetY: 580, jamOpacity: 0, force: 0 }
        ];

        // --- 缓动函数 ---
        function lerp(start, end, amt) {
            return (1 - amt) * start + amt * end;
        }
        function easeInOutQuad(t) {
            return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        }

        let startTime = null;
        let totalDuration = timeline[timeline.length - 1].t;

        function animate(timestamp) {
            if (!startTime) startTime = timestamp;
            let elapsed = (timestamp - startTime) % totalDuration;
            
            // 查找当前所处的时间段
            let currentFrame, nextFrame;
            for (let i = 0; i < timeline.length - 1; i++) {
                if (elapsed >= timeline[i].t && elapsed < timeline[i + 1].t) {
                    currentFrame = timeline[i];
                    nextFrame = timeline[i + 1];
                    break;
                }
            }

            if (!currentFrame) currentFrame = timeline[timeline.length - 2];
            if (!nextFrame) nextFrame = timeline[timeline.length - 1];

            // 计算当前段的进度 (0.0 到 1.0)
            let segmentDuration = nextFrame.t - currentFrame.t;
            let segmentElapsed = elapsed - currentFrame.t;
            let rawProgress = segmentElapsed / segmentDuration;
            let progress = easeInOutQuad(rawProgress);

            // --- 动态值插值计算 ---
            let currentY = lerp(currentFrame.targetY, nextFrame.targetY, progress);
            let currentForce = lerp(currentFrame.force, nextFrame.force, progress);
            let currentJamOpacity = currentFrame.state === 'IDLE' && nextFrame.state === 'JAM_UP' ? 
                                    lerp(0, 1, progress) : 
                                    (currentFrame.state === 'RESET' ? lerp(1, 0, progress) : currentFrame.jamOpacity);

            // --- 特殊状态逻辑处理 ---
            let isJammed = currentFrame.state === 'JAMMED';
            let isReleased = currentFrame.state === 'RELEASE' || currentFrame.state === 'RESET';
            
            // 1. 磁吸底座脱落逻辑 (位移与旋转)
            let baseRot = 0;
            let baseXOffset = 0;
            let baseYOffset = 0;

            if (currentFrame.state === 'JAMMED') {
                // 卡滞阶段:推力>50,触发脱落临界状态(微小震动预警)
                if (currentForce > 45 && currentForce <= config.magThreshold) {
                    baseRot = Math.sin(timestamp / 20) * 1; // 震动
                }
            } else if (isReleased) {
                // 完全脱落阶段
                let releaseProgress = 1;
                if (currentFrame.state === 'RELEASE') {
                    releaseProgress = Math.min(1, rawProgress * 3); // 快速脱落
                } else if (currentFrame.state === 'RESET') {
                    releaseProgress = 1 - progress; // 复位归位
                }
                baseRot = -15 * releaseProgress; // 倾斜
                baseXOffset = -10 * releaseProgress; // 向左弹出
                baseYOffset = 25 * releaseProgress; // 向下掉落
            }

            let currentBaseX = config.baseStaticX + baseXOffset;
            let currentBaseY = config.baseStaticY + baseYOffset;

            // 2. 柔性曲臂弯曲变形逻辑 (二次贝塞尔曲线)
            // 正常状态:控制点X稍微偏左,使其呈现平滑的C型
            // 卡滞受力状态:推力变大,控制点X极度偏左,呈现严重的弓形弯曲
            let sliderCY = currentY + 20; // 滑块中心连接点
            let baseCX = currentBaseX;
            let baseCY = currentBaseY;
            
            // 基础弯曲度
            let ctrlX = baseCX - 60;
            let ctrlY = (baseCY + sliderCY) / 2;

            if (isJammed) {
                // 力度越大,弓得越厉害
                let stressBend = Math.max(0, currentForce - 15) * 2.5; 
                ctrlX -= stressBend;
            }

            // --- 渲染更新 SVG ---
            
            // 滑块位置
            els.slider.setAttribute('transform', `translate(0, ${currentY - 580})`);
            
            // 卡滞物透明度
            els.jamBlock.setAttribute('opacity', currentJamOpacity);

            // 磁吸底座位置旋转 (以右上角 570, 490 为基准点进行旋转,但其实底座是从胶板分离的)
            // 修改为以底座中心偏下为旋转轴系点更加自然
            els.magnetBase.setAttribute('transform', `translate(${baseXOffset}, ${baseYOffset}) rotate(${baseRot}, 550, 560)`);
            
            // 磁力线可见度
            els.magFields.setAttribute('opacity', isReleased ? 0 : 0.6);

            // 曲臂路径更新
            let armPath = `M ${baseCX} ${baseCY} Q ${ctrlX} ${ctrlY} 455 ${sliderCY}`;
            els.arm.setAttribute('d', armPath);
            els.armStress.setAttribute('d', armPath);
            
            // 曲臂受力高亮 (红色发光)
            let stressOpacity = 0;
            if (currentForce > 20 && !isReleased) {
                stressOpacity = Math.min(1, (currentForce - 20) / 30);
            }
            els.armStress.setAttribute('opacity', stressOpacity);

            // 摩擦火花 / 接触高亮
            let isMoving = Math.abs(currentFrame.targetY - nextFrame.targetY) > 0 && currentForce > 0;
            els.frictionSpark.setAttribute('opacity', isMoving ? 0.8 + Math.sin(timestamp/50)*0.2 : 0);

            // 动态标注线更新,保持追踪
            els.lineSlider.setAttribute('d', `M 435 ${sliderCY} L 350 ${sliderCY} L 330 650 L 320 650`);
            // 控制点Y变化导致辅助线微调
            els.lineArm.setAttribute('d', `M ${ctrlX+20} ${ctrlY} L 400 ${ctrlY} L 380 350 L 320 350`);

            // --- UI 面板数据更新 ---
            els.uiPhase.innerText = currentFrame.desc;
            els.uiPhase.style.color = (isJammed || isReleased) ? "var(--neon-orange)" : "var(--cyan-glow)";
            
            els.uiForce.innerText = currentForce.toFixed(1) + " N";
            if (currentForce > config.magThreshold) {
                els.uiForce.className = "value warning";
            } else {
                els.uiForce.className = "value";
                els.uiForce.style.color = currentForce > 30 ? "var(--neon-orange)" : "var(--neon-green)";
            }

            if (isReleased) {
                els.uiMagnetStatus.innerHTML = "<span style='color:var(--neon-pink)'>脱落卸力 [⚠️保护触发]</span>";
            } else if (currentForce > 45) {
                els.uiMagnetStatus.innerHTML = "<span style='color:var(--neon-orange)'>临界状态 [⚡]</span>";
            } else {
                els.uiMagnetStatus.innerHTML = "<span style='color:var(--neon-green)'>吸附稳定 [🔒]</span>";
            }

            requestAnimationFrame(animate);
        }

        // 页面加载完成后自动启动动画,无需人工交互
        window.addEventListener('DOMContentLoaded', () => {
            requestAnimationFrame(animate);
        });

    </script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分