分享图
动画工坊
引擎就绪
<!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>
    <style>
        :root {
            --bg-color: #050914;
            --grid-color: rgba(0, 255, 255, 0.08);
            --neon-cyan: #00f3ff;
            --neon-blue: #0088ff;
            --neon-orange: #ffaa00;
            --neon-red: #ff2a2a;
            --neon-green: #00ffaa;
            --glass-bg: rgba(5, 12, 26, 0.6);
            --glass-border: rgba(0, 243, 255, 0.3);
            --font-main: 'Segoe UI', system-ui, -apple-system, sans-serif;
            --font-mono: 'Consolas', 'Courier New', monospace;
        }

        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: var(--bg-color);
            background-image: 
                radial-gradient(circle at 50% 50%, #0a1128 0%, #03050a 100%);
            color: #fff;
            font-family: var(--font-main);
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        #app-container {
            position: relative;
            width: 100%;
            height: 100%;
            max-width: 1600px;
            max-height: 900px;
            display: flex;
            flex-direction: column;
            box-shadow: inset 0 0 100px rgba(0,0,0,0.8);
        }

        /* 顶部控制台 HUD */
        .hud-panel {
            position: absolute;
            background: var(--glass-bg);
            border: 1px solid var(--glass-border);
            border-radius: 8px;
            padding: 20px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0,0,0,0.5), inset 0 0 20px rgba(0, 243, 255, 0.05);
            z-index: 10;
        }

        .hud-top-left {
            top: 30px;
            left: 30px;
            border-left: 4px solid var(--neon-cyan);
        }

        .hud-top-right {
            top: 30px;
            right: 30px;
            border-right: 4px solid var(--neon-orange);
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        .hud-bottom-center {
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%);
            border-bottom: 4px solid var(--neon-green);
            text-align: center;
            width: 600px;
            opacity: 0;
            transition: opacity 0.5s ease;
        }

        h1, h2, h3 {
            margin: 0;
            font-weight: 600;
            letter-spacing: 1px;
        }

        .title {
            font-size: 1.2rem;
            color: var(--neon-cyan);
            text-transform: uppercase;
            margin-bottom: 5px;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .title::before {
            content: '';
            display: inline-block;
            width: 12px;
            height: 12px;
            background: var(--neon-cyan);
            box-shadow: 0 0 10px var(--neon-cyan);
        }

        .subtitle {
            font-size: 0.85rem;
            color: #8892b0;
            font-family: var(--font-mono);
        }

        .data-row {
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-family: var(--font-mono);
            font-size: 1.1rem;
            gap: 20px;
            margin-top: 8px;
        }

        .data-label {
            color: #a8b2d1;
            font-size: 0.9rem;
        }

        .data-value {
            color: var(--neon-orange);
            font-weight: bold;
            text-shadow: 0 0 8px rgba(255, 170, 0, 0.5);
        }

        .data-value.cyan {
            color: var(--neon-cyan);
            text-shadow: 0 0 8px rgba(0, 243, 255, 0.5);
        }

        /* 控制按钮 */
        .control-group {
            display: flex;
            gap: 10px;
            margin-top: 10px;
        }

        button {
            background: rgba(0, 243, 255, 0.1);
            border: 1px solid var(--neon-cyan);
            color: var(--neon-cyan);
            padding: 8px 16px;
            font-family: var(--font-main);
            font-size: 0.9rem;
            cursor: pointer;
            border-radius: 4px;
            transition: all 0.3s;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        button:hover {
            background: var(--neon-cyan);
            color: #000;
            box-shadow: 0 0 15px var(--neon-cyan);
        }

        button.active {
            background: var(--neon-cyan);
            color: #000;
            font-weight: bold;
            box-shadow: 0 0 15px var(--neon-cyan);
        }

        button.btn-ice {
            border-color: #a0c4ff;
            color: #a0c4ff;
        }
        button.btn-ice.active, button.btn-ice:hover {
            background: #a0c4ff;
            color: #000;
            box-shadow: 0 0 15px #a0c4ff;
        }

        /* SVG 容器 */
        #svg-container {
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
        }

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

        /* 状态指示器 */
        .status-indicator {
            display: inline-block;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 0.8rem;
            font-weight: bold;
            font-family: var(--font-mono);
            margin-top: 10px;
        }
        
        .status-cruise { background: rgba(0, 255, 170, 0.2); border: 1px solid var(--neon-green); color: var(--neon-green); }
        .status-eject { background: rgba(255, 42, 42, 0.2); border: 1px solid var(--neon-red); color: var(--neon-red); }
        .status-brake { background: rgba(255, 170, 0, 0.2); border: 1px solid var(--neon-orange); color: var(--neon-orange); }
        .status-stop { background: rgba(0, 243, 255, 0.2); border: 1px solid var(--neon-cyan); color: var(--neon-cyan); }

        /* 扫描线叠层 */
        .scanlines {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(
                to bottom,
                rgba(255,255,255,0),
                rgba(255,255,255,0) 50%,
                rgba(0,0,0,0.2) 50%,
                rgba(0,0,0,0.2)
            );
            background-size: 100% 4px;
            pointer-events: none;
            z-index: 20;
            opacity: 0.3;
        }

        .ifr-highlight {
            font-size: 1.4rem;
            color: var(--neon-green);
            text-shadow: 0 0 10px var(--neon-green);
            margin-bottom: 10px;
        }
        
        .ifr-desc {
            color: #e2e8f0;
            font-size: 1rem;
            line-height: 1.5;
        }
    </style>
</head>
<body>

<div id="app-container">
    <div class="scanlines"></div>

    <!-- 左上角:系统状态 -->
    <div class="hud-panel hud-top-left">
        <div class="title">安全脱离系统监控台</div>
        <div class="subtitle">SYS.VER 4.2.0 | TRIZ 理想解演示</div>
        
        <div style="margin-top: 20px;">
            <div class="data-label">当前执行阶段</div>
            <div id="phase-indicator" class="status-indicator status-cruise">01 - 正常巡航</div>
        </div>

        <div style="margin-top: 20px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 15px;">
            <div class="data-label">环境模拟设置</div>
            <div class="control-group">
                <button id="btn-dry" class="active" onclick="setRoadCondition('dry')">标准柏油路面 (μ>0.8)</button>
                <button id="btn-ice" class="btn-ice" onclick="setRoadCondition('ice')">冰雪低附路面 (μ<0.3)</button>
            </div>
        </div>
    </div>

    <!-- 右上角:实时遥测数据 -->
    <div class="hud-panel hud-top-right">
        <div class="title">实时运动学遥测</div>
        <div class="subtitle">参考系:追踪脱离电池包</div>
        
        <div class="data-row">
            <span class="data-label">对地相对速度:</span>
            <span class="data-value cyan" id="data-speed">120.0 km/h</span>
        </div>
        <div class="data-row">
            <span class="data-label">实时摩擦系数:</span>
            <span class="data-value" id="data-friction">0.00 μ</span>
        </div>
        <div class="data-row">
            <span class="data-label">制动滑行距离:</span>
            <span class="data-value" id="data-distance">0.00 m</span>
        </div>
        <div class="data-row">
            <span class="data-label">气囊内部压力:</span>
            <span class="data-value" id="data-pressure">0 kPa</span>
        </div>
    </div>

    <!-- 底部居中:TRIZ 理想解说明 (动画最后阶段显示) -->
    <div class="hud-panel hud-bottom-center" id="ifr-panel">
        <div class="ifr-highlight">最终理想解 (IFR) 达成</div>
        <div class="ifr-desc">
            巧妙利用脱离瞬间的压缩空气与自身重力,将“翻滚的危险源”直接转化为<b>高阻力制动锚</b>。<br>
            芳纶气囊消除硬着陆冲击,并在 <span id="ifr-dist-text" style="color:var(--neon-orange); font-weight:bold;">2.0</span> 米内强行终止滑行,杜绝次生灾害。
        </div>
    </div>

    <!-- 核心 SVG 动画区 -->
    <div id="svg-container">
        <svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
            <defs>
                <!-- 发光滤镜 -->
                <filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="8" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="glow-orange" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="15" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>
                <filter id="glow-red" x="-20%" y="-20%" width="140%" height="140%">
                    <feGaussianBlur stdDeviation="10" result="blur" />
                    <feComposite in="SourceGraphic" in2="blur" operator="over" />
                </filter>

                <!-- 芳纶纤维纹理 -->
                <pattern id="aramid-texture" width="10" height="10" patternUnits="userSpaceOnUse">
                    <path d="M0 0L10 10ZM10 0L0 10Z" stroke="rgba(0,0,0,0.3)" stroke-width="1" />
                    <rect width="10" height="10" fill="url(#airbag-grad)" fill-opacity="0.8" />
                </pattern>
                <linearGradient id="airbag-grad" x1="0%" y1="0%" x2="0%" y2="100%">
                    <stop offset="0%" stop-color="#ffcc00" />
                    <stop offset="100%" stop-color="#ff6600" />
                </linearGradient>

                <!-- 背景网格 -->
                <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="1"/>
                </pattern>
                
                <!-- 运动模糊线条滤镜 -->
                <filter id="motion-blur" x="-50%" y="-50%" width="200%" height="200%">
                    <feGaussianBlur stdDeviation="20 0" result="blur" />
                </filter>
            </defs>

            <!-- 背景与网格 -->
            <rect width="100%" height="100%" fill="url(#grid)" />
            
            <g id="world-transform">
                <!-- 动态路面线 -->
                <g id="road-lines" stroke="rgba(255,255,255,0.4)" stroke-width="4" stroke-dasharray="80 120">
                    <line x1="-1000" y1="700" x2="3000" y2="700" />
                    <line x1="-1000" y1="730" x2="3000" y2="730" opacity="0.5" stroke-dasharray="40 60" />
                    <line x1="-1000" y1="760" x2="3000" y2="760" opacity="0.2" stroke-dasharray="20 40" />
                </g>

                <!-- 路面高亮摩擦区 -->
                <ellipse id="friction-glow" cx="800" cy="700" rx="200" ry="20" fill="rgba(255, 60, 0, 0)" filter="url(#glow-orange)" />

                <!-- 汽车底盘 (虚影) -->
                <g id="car-chassis" filter="url(#glow-cyan)" opacity="0.8">
                    <!-- 轮廓线框风格的底盘 -->
                    <path d="M 400 550 L 450 500 L 1150 500 L 1200 550 L 1180 620 L 420 620 Z" fill="rgba(0, 243, 255, 0.05)" stroke="var(--neon-cyan)" stroke-width="2"/>
                    <!-- 轮子 -->
                    <circle cx="500" cy="620" r="40" fill="none" stroke="var(--neon-cyan)" stroke-width="2" stroke-dasharray="10 5" />
                    <circle cx="1100" cy="620" r="40" fill="none" stroke="var(--neon-cyan)" stroke-width="2" stroke-dasharray="10 5" />
                    <circle cx="500" cy="620" r="25" fill="none" stroke="var(--neon-cyan)" stroke-width="1" />
                    <circle cx="1100" cy="620" r="25" fill="none" stroke="var(--neon-cyan)" stroke-width="1" />
                    <!-- 车体科技线条 -->
                    <line x1="450" y1="520" x2="1150" y2="520" stroke="rgba(0, 243, 255, 0.5)" stroke-width="1" />
                    <text x="750" y="480" fill="var(--neon-cyan)" font-family="var(--font-mono)" font-size="14" letter-spacing="2">EV CHASSIS // PLATFORM 9</text>
                </g>

                <!-- 弹射指示箭头 -->
                <g id="eject-arrow" opacity="0" filter="url(#glow-red)">
                    <path d="M 800 420 L 820 380 L 780 380 Z" fill="var(--neon-red)"/>
                    <line x1="800" y1="380" x2="800" y2="480" stroke="var(--neon-red)" stroke-width="4" stroke-dasharray="10 5"/>
                    <text x="820" y="440" fill="var(--neon-red)" font-family="var(--font-main)" font-size="16" font-weight="bold">侧推爆破激活</text>
                </g>

                <!-- 电池包系统 -->
                <g id="battery-system">
                    <!-- 芳纶气囊 (初始隐藏/压缩在电池底部) -->
                    <g id="airbag" transform="scale(1, 0)" transform-origin="800 590">
                        <path d="M 620 590 Q 600 680 650 695 L 950 695 Q 1000 680 980 590 Z" fill="url(#aramid-texture)" stroke="var(--neon-orange)" stroke-width="3" filter="url(#glow-orange)"/>
                        <!-- 气囊上的纹理线条 -->
                        <path d="M 640 620 Q 800 660 960 620" fill="none" stroke="rgba(255,255,255,0.4)" stroke-width="2"/>
                        <path d="M 630 650 Q 800 680 970 650" fill="none" stroke="rgba(255,255,255,0.4)" stroke-width="2"/>
                        <text x="800" y="660" fill="#fff" font-family="var(--font-mono)" font-size="14" text-anchor="middle" font-weight="bold" text-shadow="0 0 5px #000">陶瓷基耐高温芳纶材质</text>
                    </g>

                    <!-- 电池本体 -->
                    <g id="battery-pack">
                        <rect x="650" y="550" width="300" height="40" rx="5" fill="#1a1e29" stroke="var(--neon-orange)" stroke-width="2" />
                        <!-- 内部电芯结构 -->
                        <rect x="660" y="555" width="40" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        <rect x="710" y="555" width="40" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        <rect x="760" y="555" width="40" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        <rect x="810" y="555" width="40" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        <rect x="860" y="555" width="40" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        <rect x="910" y="555" width="30" height="30" fill="rgba(255, 170, 0, 0.2)" stroke="var(--neon-orange)" stroke-width="1"/>
                        
                        <!-- 警示标志 -->
                        <path d="M 800 560 L 810 580 L 790 580 Z" fill="var(--neon-orange)" />
                        <text x="800" y="585" fill="#1a1e29" font-family="var(--font-main)" font-size="10" font-weight="bold" text-anchor="middle">!</text>
                    </g>
                </g>

                <!-- 制动火花粒子效果 -->
                <g id="sparks" opacity="0" filter="url(#motion-blur)"></g>

                <!-- 信息标注连线 (动态显示) -->
                <g id="annotations" opacity="0">
                    <!-- 摩擦力指示 -->
                    <line x1="800" y1="700" x2="800" y2="760" stroke="var(--neon-green)" stroke-width="2" />
                    <circle cx="800" cy="700" r="4" fill="var(--neon-green)" />
                    <text x="810" y="750" fill="var(--neon-green)" font-family="var(--font-main)" font-size="16" font-weight="bold" filter="url(#glow-cyan)">超高地面摩擦阻力 (μ > 0.8)</text>
                    
                    <!-- 气囊作用指示 -->
                    <line x1="900" y1="650" x2="1050" y2="600" stroke="var(--neon-orange)" stroke-width="2" />
                    <circle cx="900" cy="650" r="4" fill="var(--neon-orange)" />
                    <text x="1060" y="605" fill="var(--neon-orange)" font-family="var(--font-main)" font-size="16" font-weight="bold">柔性减震,防止外壳破裂起火</text>
                </g>
            </g>
        </svg>
    </div>
</div>

<script>
    /**
     * 物理引擎与动画调度器
     * 采用“相机锁定脱离电池包”的参考系
     */
    
    // --- 配置与状态变量 ---
    const v0 = 33.33; // 初始速度 m/s (约120km/h)
    const pixelsPerMeter = 40; // 视觉缩放比例
    
    let simConfig = {
        frictionCoeff: 0.85, // 默认高摩擦
        roadType: 'dry'
    };

    let state = {
        phase: 0, // 0:巡航, 1:弹射脱离, 2:气囊充气, 3:触地制动, 4:完全停止
        time: 0,
        batterySpeed: v0, // 电池相对地面的速度 m/s
        carX: 0, // 汽车相对电池的距离 (m)
        batteryY: 0, // 电池下落距离 (m)
        slideDistance: 0, // 滑行距离 (m)
        roadPos: 0, // 路面纹理偏移 (px)
        airbagScale: 0, // 0 to 1
        pressure: 0,
        sparkIntensity: 0
    };

    let animationFrameId;
    let lastTime = performance.now();

    // --- DOM 元素引用 ---
    const dom = {
        roadLines: document.getElementById('road-lines'),
        carChassis: document.getElementById('car-chassis'),
        batterySystem: document.getElementById('battery-system'),
        airbag: document.getElementById('airbag'),
        sparks: document.getElementById('sparks'),
        ejectArrow: document.getElementById('eject-arrow'),
        annotations: document.getElementById('annotations'),
        frictionGlow: document.getElementById('friction-glow'),
        
        // HUD
        phaseIndicator: document.getElementById('phase-indicator'),
        dataSpeed: document.getElementById('data-speed'),
        dataFriction: document.getElementById('data-friction'),
        dataDistance: document.getElementById('data-distance'),
        dataPressure: document.getElementById('data-pressure'),
        ifrPanel: document.getElementById('ifr-panel'),
        ifrDistText: document.getElementById('ifr-dist-text'),
        
        // 按钮
        btnDry: document.getElementById('btn-dry'),
        btnIce: document.getElementById('btn-ice')
    };

    // --- 初始化火花粒子 ---
    const sparkCount = 30;
    for(let i=0; i<sparkCount; i++) {
        let line = document.createElementNS("http://www.w3.org/2000/svg", "line");
        line.setAttribute("stroke", "#ffaa00");
        line.setAttribute("stroke-width", Math.random() * 3 + 1);
        dom.sparks.appendChild(line);
    }

    // --- 交互控制 ---
    window.setRoadCondition = function(type) {
        simConfig.roadType = type;
        if(type === 'dry') {
            simConfig.frictionCoeff = 0.85;
            dom.btnDry.classList.add('active');
            dom.btnIce.classList.remove('active');
        } else {
            simConfig.frictionCoeff = 0.25; // 冰雪路面摩擦小
            dom.btnIce.classList.add('active');
            dom.btnDry.classList.remove('active');
        }
        // 重置动画
        resetSimulation();
    };

    function resetSimulation() {
        state = {
            phase: 0,
            time: 0,
            batterySpeed: v0,
            carX: 0,
            batteryY: 0,
            slideDistance: 0,
            roadPos: 0,
            airbagScale: 0,
            pressure: 0,
            sparkIntensity: 0
        };
        dom.ifrPanel.style.opacity = '0';
        dom.annotations.setAttribute('opacity', '0');
        dom.frictionGlow.setAttribute('fill', 'rgba(255, 60, 0, 0)');
        updateHUD();
    }

    // --- 主循环 ---
    function loop(currentTime) {
        let dt = (currentTime - lastTime) / 1000; // 秒
        if (dt > 0.1) dt = 0.1; // 防止标签页休眠导致步长过大
        lastTime = currentTime;

        updatePhysics(dt);
        renderVisuals();
        updateHUD();

        animationFrameId = requestAnimationFrame(loop);
    }

    // --- 物理状态更新 ---
    function updatePhysics(dt) {
        state.time += dt;

        // 时间轴编排
        // 0s - 1.5s: 正常巡航
        // 1.5s - 1.8s: 触发弹射
        // 1.8s - 2.2s: 下落与气囊爆开
        // 2.2s - ... : 触地制动直到停止
        // 停止后停留4秒,然后重置

        if (state.time < 1.5) {
            state.phase = 0;
        } 
        else if (state.time >= 1.5 && state.time < 1.8) {
            state.phase = 1;
            state.batteryY += 2 * dt; // 开始下落
        }
        else if (state.time >= 1.8 && state.time < 2.2) {
            state.phase = 2;
            state.batteryY += 10 * dt; // 加速下落
            if(state.batteryY > 1.8) state.batteryY = 1.8; // 落地最大高度
            
            // 气囊充气 0->1
            state.airbagScale = Math.min(1, (state.time - 1.8) / 0.3);
            state.pressure = state.airbagScale * 350; // kPa
        }
        else if (state.time >= 2.2 && state.batterySpeed > 0) {
            state.phase = 3;
            // 核心 IFR 机制:强力摩擦制动
            let deceleration = simConfig.frictionCoeff * 9.8; // a = μg
            state.batterySpeed -= deceleration * dt;
            if (state.batterySpeed < 0) state.batterySpeed = 0;
            
            // 记录滑行距离
            let ds = state.batterySpeed * dt;
            state.slideDistance += ds;
            
            state.sparkIntensity = (state.batterySpeed / v0); // 速度越快火花越亮
        }
        else if (state.batterySpeed === 0) {
            if(state.phase !== 4) {
                state.phase = 4;
                state.stopTime = state.time; // 记录停止时刻
            }
            state.sparkIntensity = 0;
            
            // 循环重置机制
            if(state.time > state.stopTime + 5.0) {
                resetSimulation();
            }
        }

        // 运动学积分 (基于“相机跟随电池”的坐标系)
        // 电池保持在中心。路面相对向左移动。
        state.roadPos -= state.batterySpeed * pixelsPerMeter * dt;
        
        // 汽车以 v0 的恒定速度前进,相对电池的速度是 (v0 - batterySpeed)
        state.carX += (v0 - state.batterySpeed) * pixelsPerMeter * dt;
    }

    // --- 渲染更新 ---
    function renderVisuals() {
        // 1. 路面滚动
        dom.roadLines.setAttribute('transform', `translate(${state.roadPos % 200}, 0)`);

        // 2. 汽车远离
        dom.carChassis.setAttribute('transform', `translate(${state.carX}, ${-state.carX * 0.05})`); // 伴随轻微上升感
        dom.carChassis.setAttribute('opacity', Math.max(0, 0.8 - state.carX / 1000)); // 渐隐

        // 3. 电池包弹射下落与气囊
        dom.batterySystem.setAttribute('transform', `translate(0, ${state.batteryY * pixelsPerMeter})`);
        
        // 气囊缩放与弹性动画
        let currentScale = state.airbagScale;
        if(state.phase === 3) {
            // 制动时的挤压变形抖动
            let jitter = Math.sin(state.time * 50) * 0.05 * state.sparkIntensity;
            currentScale = 1 - jitter;
            dom.frictionGlow.setAttribute('fill', `rgba(255, 60, 0, ${0.4 * state.sparkIntensity})`);
        }
        dom.airbag.setAttribute('transform', `scale(1, ${currentScale})`);

        // 4. 弹射箭头
        if(state.phase === 1) {
            dom.ejectArrow.setAttribute('opacity', 1);
            let arrowY = Math.sin(state.time * 20) * 10; // 闪烁抖动
            dom.ejectArrow.setAttribute('transform', `translate(0, ${arrowY})`);
        } else {
            dom.ejectArrow.setAttribute('opacity', 0);
        }

        // 5. 制动火花粒子
        if(state.phase === 3 && state.sparkIntensity > 0) {
            dom.sparks.setAttribute('opacity', state.sparkIntensity);
            let lines = dom.sparks.children;
            for(let i=0; i<lines.length; i++) {
                // 火花从气囊底部的接触面产生并向后飞(向左,因为电池相对路面向右滑行)
                // 实际上路面向左走,火花应该留在路面上向左飞
                let startX = 700 + Math.random() * 200;
                let startY = 695 + Math.random() * 5;
                let length = (Math.random() * 100 + 50) * state.sparkIntensity;
                
                // 偶尔重置火花位置
                if(Math.random() < 0.2) {
                    lines[i].setAttribute('x1', startX);
                    lines[i].setAttribute('y1', startY);
                    lines[i].setAttribute('x2', startX - length);
                    lines[i].setAttribute('y2', startY - (Math.random()*10 - 5));
                } else {
                    // 让火花随路面后退
                    let x1 = parseFloat(lines[i].getAttribute('x1')) - state.batterySpeed * pixelsPerMeter * 0.016;
                    let x2 = parseFloat(lines[i].getAttribute('x2')) - state.batterySpeed * pixelsPerMeter * 0.016;
                    lines[i].setAttribute('x1', x1);
                    lines[i].setAttribute('x2', x2);
                }
            }
        } else {
            dom.sparks.setAttribute('opacity', 0);
        }

        // 6. 后期标注与理想解展示
        if(state.phase >= 3) {
            dom.annotations.setAttribute('opacity', Math.min(1, (state.time - 2.2) * 2));
            if(simConfig.roadType === 'ice') {
                dom.annotations.querySelector('text').textContent = "低摩擦冰雪路面 (μ < 0.3)";
                dom.annotations.querySelector('text').setAttribute('fill', '#a0c4ff');
                dom.annotations.querySelector('line').setAttribute('stroke', '#a0c4ff');
                dom.annotations.querySelector('circle').setAttribute('fill', '#a0c4ff');
            } else {
                dom.annotations.querySelector('text').textContent = "超高地面摩擦阻力 (μ > 0.8)";
                dom.annotations.querySelector('text').setAttribute('fill', 'var(--neon-green)');
                dom.annotations.querySelector('line').setAttribute('stroke', 'var(--neon-green)');
                dom.annotations.querySelector('circle').setAttribute('fill', 'var(--neon-green)');
            }
        }

        if(state.phase === 4 && state.time - state.stopTime > 0.5) {
            dom.ifrPanel.style.opacity = '1';
            dom.ifrDistText.textContent = state.slideDistance.toFixed(1);
            if(simConfig.roadType === 'ice') {
                dom.ifrDistText.style.color = '#a0c4ff';
            } else {
                dom.ifrDistText.style.color = 'var(--neon-green)';
            }
        }
    }

    // --- HUD 数据更新 ---
    function updateHUD() {
        // 状态指示器
        let phaseText, phaseClass;
        switch(state.phase) {
            case 0: phaseText = "01 - 正常巡航阶段"; phaseClass = "status-cruise"; break;
            case 1: phaseText = "02 - 侧向推力爆破脱离"; phaseClass = "status-eject"; break;
            case 2: phaseText = "03 - 底部耐高温气囊充气"; phaseClass = "status-brake"; break;
            case 3: phaseText = "04 - 触地强力摩擦制动"; phaseClass = "status-brake"; break;
            case 4: phaseText = "05 - 锚定停滞 (完全消除隐患)"; phaseClass = "status-stop"; break;
        }
        dom.phaseIndicator.textContent = phaseText;
        dom.phaseIndicator.className = `status-indicator ${phaseClass}`;

        // 遥测数据
        dom.dataSpeed.textContent = (state.batterySpeed * 3.6).toFixed(1) + " km/h";
        
        let displayFriction = state.phase >= 3 ? simConfig.frictionCoeff.toFixed(2) : "0.00";
        dom.dataFriction.textContent = displayFriction + " μ";
        
        dom.dataDistance.textContent = state.slideDistance.toFixed(2) + " m";
        dom.dataPressure.textContent = Math.floor(state.pressure) + " kPa";

        // 颜色反馈
        if(state.batterySpeed < 5) dom.dataSpeed.classList.remove('cyan');
        else dom.dataSpeed.classList.add('cyan');
    }

    // --- 启动动画 ---
    window.addEventListener('DOMContentLoaded', () => {
        resetSimulation();
        lastTime = performance.now();
        animationFrameId = requestAnimationFrame(loop);
    });

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