独立渲染引擎就绪引擎就绪
<!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>
:root {
--bg-color: #050505;
--grid-color: rgba(255, 255, 255, 0.04);
--panel-bg: rgba(10, 10, 12, 0.85);
--panel-border: rgba(255, 255, 255, 0.1);
--accent-cyan: #00f0ff;
--accent-green: #00ff66;
--accent-red: #ff003c;
--accent-amber: #ffb700;
--text-main: #e2e8f0;
--text-dim: #94a3b8;
--font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
--font-sans: system-ui, -apple-system, sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: var(--font-sans);
overflow: hidden;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 30px 30px;
background-position: center center;
}
/* 核心视图容器 */
.viewport {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 2vw;
padding: 80px;
}
.svg-container {
flex: 1;
height: 100%;
max-width: 800px;
position: relative;
}
svg {
width: 100%;
height: 100%;
filter: drop-shadow(0 0 20px rgba(0, 240, 255, 0.05));
}
/* 信息面板 (HUD) */
.hud-panel {
position: absolute;
background: var(--panel-bg);
border: 1px solid var(--panel-border);
border-radius: 6px;
padding: 16px;
backdrop-filter: blur(8px);
font-family: var(--font-mono);
font-size: 12px;
z-index: 10;
box-shadow: 0 4px 24px rgba(0,0,0,0.5);
pointer-events: none;
}
.hud-top-left { top: 24px; left: 24px; width: 320px; }
.hud-bottom-left { bottom: 24px; left: 24px; width: 320px; }
.hud-top-right { top: 24px; right: 24px; width: 280px; }
.hud-bottom-right { bottom: 24px; right: 24px; width: 280px; }
.hud-title {
color: var(--accent-cyan);
font-size: 14px;
font-weight: bold;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 1px;
border-bottom: 1px solid var(--panel-border);
padding-bottom: 4px;
}
.hud-row {
display: flex;
justify-content: space-between;
margin-bottom: 6px;
}
.hud-row.highlight { color: var(--accent-amber); }
.hud-row.success { color: var(--accent-green); }
.hud-row.danger { color: var(--accent-red); }
.ifr-tag {
display: inline-block;
background: rgba(0, 240, 255, 0.1);
color: var(--accent-cyan);
padding: 2px 6px;
border-radius: 4px;
font-size: 10px;
margin-bottom: 8px;
border: 1px solid rgba(0, 240, 255, 0.2);
}
/* 标签指示器 */
.view-label {
position: absolute;
bottom: -30px;
width: 100%;
text-align: center;
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-dim);
letter-spacing: 2px;
}
/* 动态发光效果 */
@keyframes pulse-red {
0% { filter: drop-shadow(0 0 4px var(--accent-red)); opacity: 1; }
50% { filter: drop-shadow(0 0 12px var(--accent-red)); opacity: 0.6; }
100% { filter: drop-shadow(0 0 4px var(--accent-red)); opacity: 1; }
}
.center-warning { animation: pulse-red 1s infinite; }
</style>
</head>
<body>
<!-- HUD 面板:左上 - TRIZ IFR 理论分析 -->
<div class="hud-panel hud-top-left">
<div class="hud-title">System Architecture</div>
<div class="ifr-tag">TRIZ: 最终理想解 (IFR)</div>
<div class="hud-row" style="color: var(--text-dim); white-space: normal; line-height: 1.5; margin-bottom: 12px;">
利用"嵌套双轴"与"偏心距"资源,在极少增加复杂度的前提下,使高速铣刀绝对覆盖物理中心点,从根本上消灭线速度为零的切割死角。
</div>
<div class="hud-row"><span>Outer Shaft:</span><span id="ui-outer-status">IDLE</span></div>
<div class="hud-row"><span>Inner Z-Axis:</span><span id="ui-z-status">RETRACTED</span></div>
<div class="hud-row"><span>Cut Mode:</span><span id="ui-mode-status" class="highlight">STANDBY</span></div>
</div>
<!-- HUD 面板:左下 - 关键参数 -->
<div class="hud-panel hud-bottom-left">
<div class="hud-title">Kinematic Parameters</div>
<div class="hud-row"><span>Eccentric Offset (E):</span><span class="highlight">2.50 mm</span></div>
<div class="hud-row"><span>Cutter Radius (R):</span><span>3.50 mm</span></div>
<div class="hud-row"><span>Center Overlap:</span><span class="success">1.00 mm (Coverage)</span></div>
<div class="hud-row"><span>Motor Spin (V1):</span><span id="ui-rpm-spin">0 RPM</span></div>
<div class="hud-row"><span>Orbit Speed (V2):</span><span id="ui-rpm-orbit">0 RPM</span></div>
</div>
<!-- HUD 面板:右上 - 实时遥测数据 -->
<div class="hud-panel hud-top-right">
<div class="hud-title">Real-time Telemetry</div>
<div class="hud-row"><span>Cycle Time:</span><span id="ui-time">0.00s</span></div>
<div class="hud-row"><span>Phase:</span><span id="ui-phase">WAIT</span></div>
<div class="hud-row"><span>Orbit Angle:</span><span id="ui-angle-orbit">0.0°</span></div>
<div class="hud-row"><span>Spin Angle:</span><span id="ui-angle-spin">0.0°</span></div>
<div class="hud-row"><span>Z Depth:</span><span id="ui-z-depth">0.00 mm</span></div>
<div class="hud-row"><span>Center Speed:</span><span id="ui-center-speed" class="danger">0.0 m/s</span></div>
</div>
<!-- HUD 面板:右下 - 图例 -->
<div class="hud-panel hud-bottom-right">
<div class="hud-title">Visual Legend</div>
<div class="hud-row"><span style="color: var(--accent-red)">●</span><span> Zero-speed Deadzone</span></div>
<div class="hud-row"><span style="color: var(--accent-cyan)">—</span><span> High-speed Milling Path</span></div>
<div class="hud-row"><span style="color: var(--accent-green)">—</span><span> Orbit Trajectory</span></div>
<div class="hud-row"><span style="color: var(--text-dim)">—</span><span> Mechanical Structure</span></div>
</div>
<!-- 核心视图区 -->
<div class="viewport">
<!-- 左侧:立面机械结构剖视图 -->
<div class="svg-container">
<svg id="svg-side" viewBox="0 0 500 600">
<defs>
<linearGradient id="metal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="20%" stop-color="#334155" />
<stop offset="50%" stop-color="#475569" />
<stop offset="80%" stop-color="#334155" />
<stop offset="100%" stop-color="#1e293b" />
</linearGradient>
<linearGradient id="brass-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#78350f" />
<stop offset="50%" stop-color="#b45309" />
<stop offset="100%" stop-color="#78350f" />
</linearGradient>
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-red" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- 背景参考线 -->
<line x1="250" y1="50" x2="250" y2="550" stroke="rgba(255,255,255,0.1)" stroke-width="1" stroke-dasharray="10,5"/>
<text x="260" y="70" fill="rgba(255,255,255,0.3)" font-family="monospace" font-size="10">Absolute Center Axis</text>
<!-- 皮头与球杆底座 -->
<g id="side-cue">
<rect x="210" y="450" width="80" height="150" fill="url(#metal-grad)" stroke="#000" stroke-width="2"/>
<path d="M 210 450 Q 250 430 290 450 Z" fill="url(#brass-grad)" stroke="#000" stroke-width="1"/>
<!-- 被切割前的轮廓虚线 -->
<path d="M 210 450 Q 250 400 290 450" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="1" stroke-dasharray="4,4"/>
<!-- 动态切割成型轮廓 (由JS更新控制) -->
<path id="side-cue-tip" d="M 210 450 Q 250 450 290 450" fill="url(#brass-grad)" stroke="#000"/>
</g>
<!-- 外部主轴与侧刀 -->
<g id="side-outer-assembly">
<rect x="180" y="100" width="140" height="180" fill="url(#metal-grad)" stroke="#0f172a" stroke-width="2" opacity="0.6"/>
<!-- 侧刀 -->
<path d="M 160 280 L 180 280 L 180 350 L 170 380 L 160 380 Z" fill="#64748b" stroke="#000"/>
<path d="M 340 280 L 320 280 L 320 350 L 330 380 L 340 380 Z" fill="#64748b" stroke="#000"/>
</g>
<!-- 内部推缸轴与偏心铣刀 (受Z轴推拉与公转引起的投影X轴平移) -->
<g id="side-inner-assembly">
<!-- 偏心距参考线 -->
<line x1="250" y1="120" x2="250" y2="400" stroke="rgba(255,255,255,0.2)" stroke-dasharray="2,2"/>
<!-- 内部核心组件 (偏移一定距离E) -->
<g id="side-eccentric-core" transform="translate(40, 0)">
<line x1="250" y1="120" x2="250" y2="400" stroke="var(--accent-cyan)" stroke-width="1" stroke-dasharray="4,4" opacity="0.5"/>
<text x="255" y="240" fill="var(--accent-cyan)" font-family="monospace" font-size="10" opacity="0.8">Eccentric Axis</text>
<!-- 微型电机 -->
<rect x="220" y="150" width="60" height="120" rx="4" fill="#1e1b4b" stroke="var(--accent-cyan)" stroke-width="1.5"/>
<rect x="235" y="270" width="30" height="40" fill="#312e81" stroke="#000"/>
<!-- 高速成型铣刀 -->
<g id="side-milling-cutter">
<!-- 铣刀头: 半径比偏心距大,确保越过绝对中心线 -->
<path d="M 200 310 L 300 310 Q 250 380 200 310" fill="#0891b2" stroke="var(--accent-cyan)" stroke-width="2" filter="url(#glow-cyan)"/>
<!-- 铣刀轴心点 -->
<circle cx="250" cy="310" r="3" fill="#fff"/>
</g>
</g>
<!-- 动态标示偏心距 E -->
<path id="side-e-line" d="M 250 200 L 290 200" stroke="var(--accent-amber)" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
<text x="260" y="195" fill="var(--accent-amber)" font-family="monospace" font-size="10">E</text>
</g>
<!-- 中心死角高亮 -->
<circle id="side-center-warn" cx="250" cy="425" r="4" fill="var(--accent-red)" class="center-warning" filter="url(#glow-red)"/>
</svg>
<div class="view-label">[ X-Z CROSS SECTION / KINEMATICS ]</div>
</div>
<!-- 右侧:俯视原理轨迹图 (IFR 核心展示) -->
<div class="svg-container">
<svg id="svg-top" viewBox="0 0 500 500">
<!-- 目标皮头轮廓 -->
<circle cx="250" cy="250" r="120" fill="none" stroke="rgba(255,255,255,0.1)" stroke-width="2" stroke-dasharray="10,5"/>
<text x="250" y="120" fill="rgba(255,255,255,0.3)" font-family="monospace" font-size="10" text-anchor="middle">Cue Tip Outer Boundary</text>
<!-- 绝对中心死角标记 -->
<circle id="top-center-warn" cx="250" cy="250" r="6" fill="var(--accent-red)" class="center-warning" filter="url(#glow-red)"/>
<circle cx="250" cy="250" r="2" fill="#fff"/>
<!-- 公转轨迹 (Orbit) -->
<circle cx="250" cy="250" r="40" fill="none" stroke="var(--accent-green)" stroke-width="1" stroke-dasharray="6,4" opacity="0.4"/>
<!-- 动态切削轨迹绘制层 -->
<g id="top-trails-layer" filter="url(#glow-cyan)"></g>
<!-- 偏心铣刀组 -->
<g id="top-orbit-group">
<!-- 偏心臂 E -->
<line x1="250" y1="250" x2="290" y2="250" stroke="var(--accent-amber)" stroke-width="2"/>
<text x="265" y="240" fill="var(--accent-amber)" font-family="monospace" font-size="10">E</text>
<!-- 高速铣刀 -->
<g id="top-spin-group" transform="translate(290, 250)">
<circle cx="0" cy="0" r="56" fill="rgba(6, 182, 212, 0.1)" stroke="var(--accent-cyan)" stroke-width="1.5" stroke-dasharray="4,2"/>
<circle cx="0" cy="0" r="2" fill="var(--accent-cyan)"/>
<!-- 刀齿 -->
<polygon points="-56,0 -46,-5 -46,5" fill="#fff"/>
<polygon points="28,-48 23,-39 32,-35" fill="#fff"/>
<polygon points="28,48 23,39 32,35" fill="#fff"/>
</g>
</g>
<!-- 覆盖率高亮区域 (中心点被彻底扫过的证明) -->
<circle cx="250" cy="250" r="16" fill="none" stroke="var(--accent-cyan)" stroke-width="1" opacity="0.2"/>
</svg>
<div class="view-label">[ X-Y TOP-DOWN TRAJECTORY / IFR ]</div>
</div>
</div>
<script>
// 核心参数设定
const E = 40; // 偏心距 (视觉缩放比例)
const R = 56; // 铣刀半径 (R > E 保证覆盖中心)
const MAX_Z = 120; // Z轴最大下压行程
// 动画状态变量
let time = 0;
let phase = 'APPROACH'; // APPROACH, MILL, RETRACT, IDLE
let orbitAngle = 0;
let spinAngle = 0;
let zOffset = 0;
// 轨迹记录
const trail1 = [];
const trail2 = [];
const trail3 = [];
const MAX_TRAIL_LENGTH = 800; // 长轨迹展示致密成型过程
// DOM 元素引用
const domSideInner = document.getElementById('side-inner-assembly');
const domSideMilling = document.getElementById('side-milling-cutter');
const domSideCueTip = document.getElementById('side-cue-tip');
const domSideWarn = document.getElementById('side-center-warn');
const domTopOrbit = document.getElementById('top-orbit-group');
const domTopSpin = document.getElementById('top-spin-group');
const domTopWarn = document.getElementById('top-center-warn');
const domTrailsLayer = document.getElementById('top-trails-layer');
// 生成三个轨迹路径元素
const path1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
const path2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
const path3 = document.createElementNS("http://www.w3.org/2000/svg", "path");
[path1, path2, path3].forEach(p => {
p.setAttribute("fill", "none");
p.setAttribute("stroke", "var(--accent-cyan)");
p.setAttribute("stroke-width", "0.75");
p.setAttribute("opacity", "0.6");
domTrailsLayer.appendChild(p);
});
// UI 元素引用
const uiTime = document.getElementById('ui-time');
const uiPhase = document.getElementById('ui-phase');
const uiAngleOrbit = document.getElementById('ui-angle-orbit');
const uiAngleSpin = document.getElementById('ui-angle-spin');
const uiZDepth = document.getElementById('ui-z-depth');
const uiRPMOrbit = document.getElementById('ui-rpm-orbit');
const uiRPMSpin = document.getElementById('ui-rpm-spin');
const uiOuterStatus = document.getElementById('ui-outer-status');
const uiZStatus = document.getElementById('ui-z-status');
const uiModeStatus = document.getElementById('ui-mode-status');
const uiCenterSpeed = document.getElementById('ui-center-speed');
// 平滑插值函数
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
// 轨迹更新函数
function updateTrails(tx1, ty1, tx2, ty2, tx3, ty3) {
trail1.push(`${tx1.toFixed(1)},${ty1.toFixed(1)}`);
trail2.push(`${tx2.toFixed(1)},${ty2.toFixed(1)}`);
trail3.push(`${tx3.toFixed(1)},${ty3.toFixed(1)}`);
if (trail1.length > MAX_TRAIL_LENGTH) {
trail1.shift(); trail2.shift(); trail3.shift();
}
if (trail1.length > 1) {
path1.setAttribute("d", "M " + trail1.join(" L "));
path2.setAttribute("d", "M " + trail2.join(" L "));
path3.setAttribute("d", "M " + trail3.join(" L "));
}
}
function clearTrails() {
trail1.length = 0; trail2.length = 0; trail3.length = 0;
path1.setAttribute("d", "");
path2.setAttribute("d", "");
path3.setAttribute("d", "");
}
// 主动画循环
function animate() {
time += 1; // 帧计时器
const cycle = 1200; // 完整周期帧数
const tInCycle = time % cycle;
let orbitSpeed = 0;
let spinSpeed = 0;
// 状态机逻辑
if (tInCycle < 200) {
// 1. APPROACH: 主轴空转,内轴下压
phase = 'APPROACH';
const progress = tInCycle / 200;
zOffset = easeInOutQuad(progress) * MAX_Z;
orbitSpeed = 0.02 * progress; // 慢慢启动公转
spinSpeed = 0;
} else if (tInCycle < 900) {
// 2. MILL: 到达底部,开启高速成型铣削
phase = 'MILL';
zOffset = MAX_Z;
orbitSpeed = 0.02;
// 模拟 60 RPM 公转与 8000 RPM 自转的高比例差异
spinSpeed = 0.8;
} else if (tInCycle < 1100) {
// 3. RETRACT: 抬升内轴
phase = 'RETRACT';
const progress = (tInCycle - 900) / 200;
zOffset = MAX_Z - easeInOutQuad(progress) * MAX_Z;
orbitSpeed = 0.02 * (1 - progress);
spinSpeed = 0.8 * (1 - progress);
} else {
// 4. IDLE: 重置
phase = 'IDLE';
zOffset = 0;
orbitSpeed = 0;
spinSpeed = 0;
if (tInCycle === 1101) clearTrails();
}
// 更新角度
orbitAngle += orbitSpeed;
spinAngle += spinSpeed;
// --- 侧视图更新 (Side View) ---
// 为了体现2D下的公转,我们将内轴的X坐标根据公转角度做正弦投影平移
const sideXOffset = E * Math.cos(orbitAngle);
domSideInner.setAttribute('transform', `translate(${sideXOffset}, ${zOffset})`);
// 铣刀在侧视图中的自转视觉模拟 (3D感)
const cutterScaleX = Math.cos(spinAngle);
domSideMilling.setAttribute('transform', `scale(${cutterScaleX}, 1)`);
// 动态形成皮头顶弧的动画逻辑
if (phase === 'MILL') {
// 模拟慢慢切出完美弧度
const millProgress = (tInCycle - 200) / 700;
const controlY = 450 - (20 * millProgress);
domSideCueTip.setAttribute('d', `M 210 450 Q 250 ${controlY} 290 450 Z`);
} else if (phase === 'IDLE' || phase === 'APPROACH') {
domSideCueTip.setAttribute('d', `M 210 450 Q 250 450 290 450 Z`);
}
// 中心警告红点的消灭逻辑
const warnOpacity = phase === 'MILL' ? 0 : 1;
domSideWarn.style.opacity = warnOpacity;
domTopWarn.style.opacity = warnOpacity;
// --- 俯视图更新 (Top-Down View) ---
// 整个轨道组自转 (围绕250,250)
const orbitDeg = orbitAngle * (180 / Math.PI);
domTopOrbit.setAttribute('transform', `rotate(${orbitDeg}, 250, 250)`);
// 铣刀自身自转
const spinDeg = spinAngle * (180 / Math.PI);
domTopSpin.setAttribute('transform', `translate(290, 250) rotate(${spinDeg}, 0, 0)`);
// 计算轨迹点 (绝对坐标)
if (phase === 'MILL') {
const cx = 250, cy = 250;
const motorX = cx + E * Math.cos(orbitAngle);
const motorY = cy + E * Math.sin(orbitAngle);
// 3个刀齿的绝对位置
const a1 = orbitAngle + spinAngle;
const a2 = a1 + (2 * Math.PI / 3);
const a3 = a1 + (4 * Math.PI / 3);
const tx1 = motorX + R * Math.cos(a1);
const ty1 = motorY + R * Math.sin(a1);
const tx2 = motorX + R * Math.cos(a2);
const ty2 = motorY + R * Math.sin(a2);
const tx3 = motorX + R * Math.cos(a3);
const ty3 = motorY + R * Math.sin(a3);
updateTrails(tx1, ty1, tx2, ty2, tx3, ty3);
}
// --- UI 遥测数据更新 ---
uiTime.innerText = (time / 60).toFixed(2) + 's';
uiPhase.innerText = phase;
uiPhase.style.color = phase === 'MILL' ? 'var(--accent-green)' : 'var(--accent-amber)';
uiAngleOrbit.innerText = (orbitDeg % 360).toFixed(1) + '°';
uiAngleSpin.innerText = (spinDeg % 360).toFixed(1) + '°';
uiZDepth.innerText = (-zOffset / 10).toFixed(2) + ' mm';
uiRPMOrbit.innerText = phase === 'MILL' ? '60 RPM' : (orbitSpeed > 0 ? 'ACCEL' : '0 RPM');
uiRPMSpin.innerText = phase === 'MILL' ? '8400 RPM' : (spinSpeed > 0 ? 'ACCEL' : '0 RPM');
uiOuterStatus.innerText = (orbitSpeed > 0) ? 'ROTATING (60 RPM)' : 'IDLE';
uiOuterStatus.className = (orbitSpeed > 0) ? 'success' : '';
uiZStatus.innerText = phase === 'APPROACH' ? 'DESCENDING' : (phase === 'RETRACT' ? 'ASCENDING' : (phase === 'MILL' ? 'LOCKED (-12.0mm)' : 'RETRACTED'));
uiModeStatus.innerText = phase === 'MILL' ? 'ECCENTRIC MILLING' : 'STANDBY';
uiModeStatus.className = phase === 'MILL' ? 'success' : 'highlight';
uiCenterSpeed.innerText = phase === 'MILL' ? '8.4 m/s (OVERLAP)' : '0.0 m/s (DEAD)';
uiCenterSpeed.className = phase === 'MILL' ? 'success' : 'danger';
requestAnimationFrame(animate);
}
// 初始化启动
document.addEventListener('DOMContentLoaded', () => {
// 确保页面加载后自动无干预播放
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
/* 工业级暗色主题 */
--bg-base: #06090e;
--grid-line: rgba(45, 60, 80, 0.4);
--grid-major: rgba(60, 120, 200, 0.15);
--panel-bg: rgba(10, 15, 25, 0.75);
--panel-border: rgba(0, 255, 255, 0.15);
/* 状态色彩体系 */
--c-cyan: #00f0ff;
--c-cyan-dim: rgba(0, 240, 255, 0.3);
--c-amber: #ffb700;
--c-green: #00ff66;
--c-red: #ff3366;
--c-metal-dark: #1e293b;
--c-metal-mid: #475569;
--c-metal-light: #94a3b8;
--text-main: #e2e8f0;
--text-dim: #64748b;
--font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
--font-sans: system-ui, -apple-system, sans-serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background-color: var(--bg-base);
color: var(--text-main);
font-family: var(--font-sans);
overflow: hidden;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
/* 工程图纸网格背景 */
background-image:
linear-gradient(var(--grid-line) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
linear-gradient(var(--grid-major) 2px, transparent 2px),
linear-gradient(90deg, var(--grid-major) 2px, transparent 2px);
background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
background-position: center center;
}
.viewport {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 4vw;
padding: 60px;
}
.svg-container {
flex: 1;
height: 100%;
max-width: 600px;
position: relative;
background: radial-gradient(circle at center, rgba(0,240,255,0.03) 0%, transparent 60%);
border: 1px solid rgba(255,255,255,0.02);
border-radius: 12px;
box-shadow: inset 0 0 40px rgba(0,0,0,0.5);
}
svg {
width: 100%;
height: 100%;
display: block;
}
/* 极简工程 HUD 面板 */
.hud {
position: absolute;
background: var(--panel-bg);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid var(--panel-border);
border-radius: 4px;
padding: 12px 16px;
font-family: var(--font-mono);
font-size: 11px;
z-index: 10;
pointer-events: none;
box-shadow: 0 8px 32px rgba(0,0,0,0.6);
}
.hud-top-left { top: 20px; left: 20px; width: 340px; }
.hud-top-right { top: 20px; right: 20px; width: 260px; }
.hud-bottom-center {
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 24px;
padding: 10px 30px;
}
.hud-title {
color: var(--c-cyan);
font-size: 12px;
font-weight: 600;
margin-bottom: 8px;
padding-bottom: 4px;
border-bottom: 1px solid var(--panel-border);
letter-spacing: 1px;
display: flex;
justify-content: space-between;
}
.hud-row {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
line-height: 1.6;
}
.val-cyan { color: var(--c-cyan); }
.val-amber { color: var(--c-amber); }
.val-green { color: var(--c-green); text-shadow: 0 0 5px rgba(0,255,102,0.4); }
.val-red { color: var(--c-red); text-shadow: 0 0 5px rgba(255,51,102,0.4); }
.desc-text {
color: var(--c-metal-light);
white-space: normal;
line-height: 1.5;
margin-bottom: 8px;
font-size: 10.5px;
}
.view-label {
position: absolute;
bottom: 16px;
width: 100%;
text-align: center;
font-family: var(--font-mono);
font-size: 11px;
color: var(--c-metal-light);
letter-spacing: 2px;
text-transform: uppercase;
}
/* 动态发光与警示动画 */
@keyframes pulse-warn {
0% { filter: drop-shadow(0 0 2px var(--c-red)); opacity: 1; stroke-width: 1; }
50% { filter: drop-shadow(0 0 8px var(--c-red)); opacity: 0.5; stroke-width: 2; }
100% { filter: drop-shadow(0 0 2px var(--c-red)); opacity: 1; stroke-width: 1; }
}
.warn-pulse { animation: pulse-warn 1.5s infinite; }
.sys-status-indicator {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--c-amber);
margin-right: 6px;
}
.sys-status-indicator.active {
background: var(--c-green);
box-shadow: 0 0 8px var(--c-green);
}
</style>
</head>
<body>
<!-- HUD 面板区域 -->
<div class="hud hud-top-left">
<div class="hud-title">
<span>[SYS.01] 机械关联架构 (双套轴)</span>
<span>TRIZ / IFR</span>
</div>
<div class="desc-text">
原理:外部主轴承载侧刀(提供基准旋转),内部推缸轴硬性连接偏心法兰。<br>
成型铣刀通过法兰安装在绝对中心线偏置距 (E) 处,利用微型电机产生 8000 RPM 独立自转,并跟随内轴进行 60 RPM 公转,以此彻底消除物理中心的“零线速度死角”。
</div>
<div class="hud-row"><span>外部主轴状态 (公转基准):</span><span id="ui-outer-state" class="val-amber">待机</span></div>
<div class="hud-row"><span>内部推缸行程 (Z轴向下):</span><span id="ui-z-depth" class="val-cyan">0.00 mm</span></div>
<div class="hud-row"><span>偏心法兰偏移距 (E):</span><span class="val-cyan">18.00 mm (固定配置)</span></div>
<div class="hud-row"><span>成型铣刀半径 (R):</span><span class="val-cyan">24.00 mm (R > E 确保过心)</span></div>
</div>
<div class="hud hud-top-right">
<div class="hud-title"><span>[SYS.02] 实时遥测数据</span></div>
<div class="hud-row"><span>运行阶段:</span><span id="ui-phase" class="val-amber">初始化</span></div>
<div class="hud-row"><span>公转转速 (主电机):</span><span id="ui-orbit-rpm">0 RPM</span></div>
<div class="hud-row"><span>自转转速 (微电机):</span><span id="ui-spin-rpm">0 RPM</span></div>
<div class="hud-row"><span>物理中心点切削线速度:</span><span id="ui-center-speed" class="val-red">0.0 m/s (死角)</span></div>
<div class="hud-row" style="margin-top: 8px; border-top: 1px dashed rgba(255,255,255,0.1); padding-top: 8px;">
<span>中心光洁度预估:</span><span id="ui-quality" class="val-red">起毛/撕裂风险极高</span>
</div>
</div>
<div class="hud hud-bottom-center">
<div class="hud-row" style="margin:0; align-items:center;">
<span class="sys-status-indicator" id="ind-power"></span> 系统电源
</div>
<div class="hud-row" style="margin:0; align-items:center;">
<span class="sys-status-indicator" id="ind-mill"></span> 高速铣削
</div>
<div class="hud-row" style="margin:0; align-items:center;">
<span class="sys-status-indicator" id="ind-ifr"></span> IFR 理想解达成
</div>
</div>
<!-- 核心可视化区 -->
<div class="viewport">
<!-- 左侧:机械结构立面剖视图 -->
<div class="svg-container">
<svg id="svg-side" viewBox="0 0 500 600">
<defs>
<!-- 机械材质渐变 -->
<linearGradient id="grad-outer" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1e293b"/>
<stop offset="20%" stop-color="#334155"/>
<stop offset="50%" stop-color="#64748b"/>
<stop offset="80%" stop-color="#334155"/>
<stop offset="100%" stop-color="#1e293b"/>
</linearGradient>
<linearGradient id="grad-inner" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#0f172a"/>
<stop offset="30%" stop-color="#1e293b"/>
<stop offset="70%" stop-color="#1e293b"/>
<stop offset="100%" stop-color="#0f172a"/>
</linearGradient>
<linearGradient id="grad-motor" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#78350f"/>
<stop offset="50%" stop-color="#b45309"/>
<stop offset="100%" stop-color="#78350f"/>
</linearGradient>
<linearGradient id="grad-cuetip" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#8b4513"/>
<stop offset="50%" stop-color="#d2691e"/>
<stop offset="100%" stop-color="#8b4513"/>
</linearGradient>
<!-- 发光滤镜 -->
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 切削遮罩 -->
<clipPath id="clip-cuetip">
<!-- 动态变化的遮罩路径,用于显示皮头被削掉的过程 -->
<path id="side-cuetip-mask" d="M 190 600 L 190 400 L 310 400 L 310 600 Z" />
</clipPath>
</defs>
<!-- 绝对中心线基准 -->
<line x1="250" y1="20" x2="250" y2="580" stroke="var(--c-cyan)" stroke-width="1" stroke-dasharray="8,4" opacity="0.4"/>
<text x="255" y="40" fill="var(--c-cyan)" font-family="var(--font-mono)" font-size="10" opacity="0.6">ABSOLUTE CENTER AXIS</text>
<!-- 底部:球杆与皮头 -->
<g id="side-base">
<!-- 夹具夹持的球杆先锋套 -->
<rect x="210" y="440" width="80" height="160" fill="#cbd5e1" stroke="#0f172a" stroke-width="2"/>
<!-- 被切割的皮头 (应用了动态 Clip Path) -->
<path d="M 210 400 L 290 400 L 290 440 L 210 440 Z" fill="url(#grad-cuetip)" stroke="#000" stroke-width="1" clip-path="url(#clip-cuetip)"/>
<!-- 理想弧度虚线参考 -->
<path d="M 210 440 L 210 420 Q 250 395 290 420 L 290 440" fill="none" stroke="rgba(255,255,255,0.3)" stroke-width="1" stroke-dasharray="2,2"/>
<!-- 中心死角警示点 -->
<circle id="side-center-deadzone" cx="250" cy="400" r="5" fill="none" stroke="var(--c-red)" stroke-width="2" class="warn-pulse"/>
</g>
<!-- 外部组件 (外部主轴,固定Z高度,原位自转代表公转基准) -->
<g id="side-outer-assembly">
<!-- 外主轴剖切视窗壳体 -->
<path d="M 170 50 L 330 50 L 330 180 L 170 180 Z" fill="url(#grad-outer)" stroke="#000" stroke-width="2"/>
<!-- 内部空腔 -->
<rect x="190" y="50" width="120" height="130" fill="#020617"/>
<text x="175" y="65" fill="#94a3b8" font-family="var(--font-mono)" font-size="9">OUTER SPINDLE</text>
<!-- 侧刀支架 (固定在外轴上,负责侧边切削) -->
<rect x="150" y="180" width="20" height="260" fill="url(#grad-outer)" stroke="#000"/>
<rect x="330" y="180" width="20" height="260" fill="url(#grad-outer)" stroke="#000"/>
<polygon points="170,440 185,440 185,400 170,410" fill="#94a3b8" stroke="#000"/>
<polygon points="330,440 315,440 315,400 330,410" fill="#94a3b8" stroke="#000"/>
</g>
<!-- 内部组件 (推缸轴,随Z轴下降,同时被外轴带动产生公转视觉位移) -->
<!-- 在2D侧视图中,内轴本体居中只做Z轴移动;偏心法兰及电机做X轴投影摆动 -->
<g id="side-inner-assembly">
<!-- 内主轴 (Z轴推杆) -->
<rect id="side-inner-shaft" x="200" y="20" width="100" height="160" fill="url(#grad-inner)" stroke="#000" stroke-width="2"/>
<line x1="200" y1="180" x2="300" y2="180" stroke="var(--c-cyan)" stroke-width="2" opacity="0.5"/>
<text x="205" y="100" fill="var(--c-cyan)" font-family="var(--font-mono)" font-size="10" opacity="0.8">INNER Z-AXIS</text>
<!-- 动态连接法兰 (连接居中内轴和偏心电机) -->
<path id="side-flange" d="" fill="#475569" stroke="#000" stroke-width="2"/>
<!-- 偏心微型电机与刀具组 -->
<g id="side-eccentric-group">
<!-- 偏心轴线指示 -->
<line x1="0" y1="-30" x2="0" y2="100" stroke="var(--c-amber)" stroke-width="1" stroke-dasharray="4,4"/>
<text x="5" y="-10" fill="var(--c-amber)" font-family="var(--font-mono)" font-size="9">E-AXIS</text>
<!-- 微型电机壳体 -->
<rect x="-25" y="0" width="50" height="60" rx="4" fill="url(#grad-motor)" stroke="#000" stroke-width="2"/>
<rect x="-10" y="60" width="20" height="15" fill="#334155" stroke="#000"/>
<text x="-18" y="20" fill="#fff" font-family="var(--font-mono)" font-size="8" transform="rotate(-90, -18, 20)">8000RPM</text>
<!-- 高速成型半球铣刀 -->
<g id="side-cutter" filter="url(#glow-cyan)">
<!-- 半球形刀刃侧视 -->
<path d="M -30 75 Q 0 105 30 75 Z" fill="#00f0ff" fill-opacity="0.2" stroke="var(--c-cyan)" stroke-width="2"/>
<!-- 切削刃剖面 -->
<path d="M -30 75 L 30 75" stroke="var(--c-cyan)" stroke-width="1"/>
<circle cx="0" cy="75" r="2" fill="#fff"/>
</g>
</g>
</g>
<!-- 偏心距标注 E (固定在法兰区域) -->
<line id="side-e-line" x1="250" y1="200" x2="280" y2="200" stroke="var(--c-amber)" stroke-width="1.5" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
<circle id="side-e-point1" cx="250" cy="200" r="2" fill="var(--c-amber)"/>
<circle id="side-e-point2" cx="280" cy="200" r="2" fill="var(--c-amber)"/>
</svg>
<div class="view-label">图 1: 机械联动立面剖切图</div>
</div>
<!-- 右侧:俯视原理轨迹图 (展示绝对中心如何被完全覆盖) -->
<div class="svg-container">
<svg id="svg-top" viewBox="0 0 500 500">
<defs>
<radialGradient id="grad-base-top" cx="50%" cy="50%" r="50%">
<stop offset="80%" stop-color="#8b4513" stop-opacity="0.1"/>
<stop offset="100%" stop-color="#d2691e" stop-opacity="0.3"/>
</radialGradient>
</defs>
<!-- 皮头外轮廓与中心线 -->
<circle cx="250" cy="250" r="100" fill="url(#grad-base-top)" stroke="var(--c-metal-light)" stroke-width="2" stroke-dasharray="10,5"/>
<text x="250" y="130" fill="var(--c-metal-light)" font-family="var(--font-mono)" font-size="10" text-anchor="middle">CUE TIP BOUNDARY (Ø14.0mm)</text>
<line x1="150" y1="250" x2="350" y2="250" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
<line x1="250" y1="150" x2="250" y2="350" stroke="rgba(255,255,255,0.1)" stroke-width="1"/>
<!-- 绝对物理中心 (问题点:常规车削时线速度为0) -->
<circle id="top-center-deadzone" cx="250" cy="250" r="6" fill="var(--c-red)" class="warn-pulse"/>
<!-- 切削轨迹保留层 -->
<g id="top-trails" opacity="0.7"></g>
<!-- 动态旋转系统 -->
<g id="top-rotating-system">
<!-- 公转基准:内轴中心 (即绝对中心) -->
<circle cx="250" cy="250" r="40" fill="none" stroke="var(--c-metal-mid)" stroke-width="2"/>
<!-- 刚性连接法兰 (确保内外轴的机械约束) -->
<path id="top-flange" d="M 250 230 L 320 230 A 20 20 0 0 1 320 270 L 250 270 Z" fill="var(--c-metal-mid)" stroke="#0f172a" stroke-width="2"/>
<!-- 法兰固定螺栓视觉 -->
<circle cx="265" cy="240" r="3" fill="#1e293b"/>
<circle cx="265" cy="260" r="3" fill="#1e293b"/>
<circle cx="295" cy="250" r="4" fill="#0f172a"/>
<!-- 偏心距标注 -->
<line x1="250" y1="250" x2="320" y2="250" stroke="var(--c-amber)" stroke-width="2"/>
<text x="280" y="245" fill="var(--c-amber)" font-family="var(--font-mono)" font-size="12" font-weight="bold">E</text>
<!-- 高速铣刀盘组件 (挂载在偏心端 E 处) -->
<g id="top-cutter-group" transform="translate(320, 250)">
<!-- 电机外壳边界 -->
<circle cx="0" cy="0" r="25" fill="#b45309" stroke="#78350f" stroke-width="2"/>
<!-- 高速刀盘 R > E -->
<circle id="top-blade" cx="0" cy="0" r="75" fill="rgba(0, 240, 255, 0.1)" stroke="var(--c-cyan)" stroke-width="1.5" stroke-dasharray="4,4" filter="url(#glow-cyan)"/>
<!-- 铣刀切削刃 (3刃设计) -->
<g id="top-cutter-teeth">
<polygon points="0,-10 0,10 -75,0" fill="#fff" opacity="0.8"/>
<polygon points="-8.6,-5 8.6,5 37.5,64.9" fill="#fff" opacity="0.8"/>
<polygon points="8.6,-5 -8.6,5 37.5,-64.9" fill="#fff" opacity="0.8"/>
</g>
<!-- 偏心自转轴心 -->
<circle cx="0" cy="0" r="3" fill="#fff"/>
</g>
</g>
<!-- 提示:铣刀半径完美覆盖中心点 -->
<circle cx="250" cy="250" r="75" fill="none" stroke="var(--c-cyan-dim)" stroke-width="1" stroke-dasharray="2,4"/>
</svg>
<div class="view-label">图 2: IFR 破除死角原理俯视图</div>
</div>
</div>
<script>
/**
* 机械参数定义
*/
const PARAMS = {
E_SIDE: 35, // 侧视图偏心距投影缩放系数
E_TOP: 70, // 俯视图偏心法兰实际绘制长度
R_CUTTER: 75, // 俯视图铣刀半径 (必须大于 E 才能过中心)
Z_MAX: 135, // 内推缸最大下压行程
CYCLE: 1500, // 单次动画完整周期帧数
RPM_ORBIT: 60, // 模拟公转慢速
RPM_SPIN: 8000 // 模拟自转高速
};
// 动画状态变量
let frame = 0;
let orbitAngle = 0; // 公转角度 (弧度)
let spinAngle = 0; // 自转角度 (弧度)
let zDepth = 0; // 当前推缸下降深度
let phase = 'INIT'; // INIT, DESCEND, MILL, RETRACT
// DOM 获取
const elSideInnerShaft = document.getElementById('side-inner-shaft');
const elSideFlange = document.getElementById('side-flange');
const elSideEccGroup = document.getElementById('side-eccentric-group');
const elSideEMarker1 = document.getElementById('side-e-point1');
const elSideEMarker2 = document.getElementById('side-e-point2');
const elSideELine = document.getElementById('side-e-line');
const elSideCutter = document.getElementById('side-cutter');
const elSideMask = document.getElementById('side-cuetip-mask');
const elSideDeadzone = document.getElementById('side-center-deadzone');
const elTopSystem = document.getElementById('top-rotating-system');
const elTopTeeth = document.getElementById('top-cutter-teeth');
const elTopTrails = document.getElementById('top-trails');
const elTopDeadzone = document.getElementById('top-center-deadzone');
// UI 获取
const uiPhase = document.getElementById('ui-phase');
const uiOrbitRpm = document.getElementById('ui-orbit-rpm');
const uiSpinRpm = document.getElementById('ui-spin-rpm');
const uiCenterSpeed = document.getElementById('ui-center-speed');
const uiQuality = document.getElementById('ui-quality');
const uiZDepth = document.getElementById('ui-z-depth');
const uiOuterState = document.getElementById('ui-outer-state');
const indPower = document.getElementById('ind-power');
const indMill = document.getElementById('ind-mill');
const indIfr = document.getElementById('ind-ifr');
// 轨迹路径元素预分配
const numTrails = 3;
const trailPaths = [];
const trailData = Array(numTrails).fill().map(() => []);
const MAX_TRAIL_LEN = 120; // 防止轨迹过长卡顿,控制在体现一个过心切削即可
for(let i=0; i<numTrails; i++) {
let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('fill', 'none');
path.setAttribute('stroke', 'var(--c-cyan)');
path.setAttribute('stroke-width', '0.8');
path.setAttribute('opacity', '0.6');
elTopTrails.appendChild(path);
trailPaths.push(path);
}
// 缓动函数
const easeInOutCubic = t => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
/**
* 核心动画循环
*/
function animate() {
frame++;
const tCycle = frame % PARAMS.CYCLE;
// 速度系数
let orbitSpeed = 0;
let spinSpeed = 0;
// --- 阶段状态机逻辑 ---
if (tCycle < 200) {
// 1. DESCEND: 启动公转,内轴下降
phase = 'DESCEND';
let progress = tCycle / 200;
zDepth = easeInOutCubic(progress) * PARAMS.Z_MAX;
orbitSpeed = 0.015 * progress;
spinSpeed = 0;
clearTrails();
} else if (tCycle < 1100) {
// 2. MILL: 抵达底部,开启高速自转,进行偏心铣削
phase = 'MILL';
zDepth = PARAMS.Z_MAX;
orbitSpeed = 0.015;
spinSpeed = 0.6; // 视觉上的高速自转
} else if (tCycle < 1300) {
// 3. RETRACT: 停止高速自转,内轴回缩
phase = 'RETRACT';
let progress = (tCycle - 1100) / 200;
zDepth = PARAMS.Z_MAX - easeInOutCubic(progress) * PARAMS.Z_MAX;
orbitSpeed = 0.015 * (1 - progress);
spinSpeed = 0.6 * (1 - progress);
} else {
// 4. INIT: 复位等待
phase = 'INIT';
zDepth = 0;
orbitSpeed = 0;
spinSpeed = 0;
}
orbitAngle += orbitSpeed;
spinAngle += spinSpeed;
// --- 侧视图更新 (Side View) ---
// 内轴本体仅作Z轴下压
elSideInnerShaft.setAttribute('y', 20 + zDepth);
elSideInnerShaft.setAttribute('height', 160); // 长度保持一致或拉伸均可,这里通过改变y模拟下推
// 计算偏心电机在2D侧视下的X轴投影位置 (绕250做正弦振荡)
const motorX = 250 + PARAMS.E_SIDE * Math.cos(orbitAngle);
const motorY = 200 + zDepth; // 电机挂载在内轴底部
// 核心机械连接:动态绘制连接法兰,消除悬空感
// 从中心内轴底部 (Y: 180+zDepth, X: 200~300) 连接到电机顶部 (Y: motorY, X: motorX-25~motorX+25)
const innerBaseY = 180 + zDepth;
const pathD = `M 200 ${innerBaseY} L 300 ${innerBaseY} L ${motorX + 25} ${motorY} L ${motorX - 25} ${motorY} Z`;
elSideFlange.setAttribute('d', pathD);
// 更新电机及刀具组的位置
elSideEccGroup.setAttribute('transform', `translate(${motorX}, ${motorY})`);
// 标注线跟随
elSideEMarker1.setAttribute('cy', motorY + 30);
elSideEMarker2.setAttribute('cx', motorX);
elSideEMarker2.setAttribute('cy', motorY + 30);
elSideELine.setAttribute('y1', motorY + 30);
elSideELine.setAttribute('x2', motorX);
elSideELine.setAttribute('y2', motorY + 30);
// 刀具自转3D投影效果
const scaleX = Math.cos(spinAngle);
elSideCutter.setAttribute('transform', `translate(0,0) scale(${scaleX}, 1)`);
// 皮头切削遮罩形态演化 (基于相位)
if (phase === 'MILL') {
// 铣削过程中,弧顶渐渐形成
let millProgress = Math.min((tCycle - 200) / 600, 1); // 前600帧切完
let cpY = 400 - (18 * millProgress); // 控制点下降,两边保持400
elSideMask.setAttribute('d', `M 190 600 L 190 400 Q 250 ${cpY} 310 400 L 310 600 Z`);
} else if (phase === 'INIT' || phase === 'DESCEND') {
elSideMask.setAttribute('d', `M 190 600 L 190 400 L 310 400 L 310 600 Z`); // 平头
}
// 警示红点控制
const isMill = phase === 'MILL';
elSideDeadzone.style.opacity = isMill ? '0' : '1';
elTopDeadzone.style.opacity = isMill ? '0' : '1';
// --- 俯视图更新 (Top View) ---
const orbitDeg = orbitAngle * (180 / Math.PI);
const spinDeg = spinAngle * (180 / Math.PI);
// 整体系统公转
elTopSystem.setAttribute('transform', `rotate(${orbitDeg}, 250, 250)`);
// 铣刀刃自转
elTopTeeth.setAttribute('transform', `rotate(${spinDeg}, 0, 0)`);
// 绘制过心切削轨迹
if (isMill) {
const cx = 250, cy = 250;
// 电机实际中心坐标
const mx = cx + PARAMS.E_TOP * Math.cos(orbitAngle);
const my = cy + PARAMS.E_TOP * Math.sin(orbitAngle);
// 3个刀尖的绝对坐标
const a1 = orbitAngle + spinAngle;
const a2 = a1 + (2 * Math.PI / 3);
const a3 = a1 + (4 * Math.PI / 3);
const pts = [
{x: mx + PARAMS.R_CUTTER * Math.cos(a1), y: my + PARAMS.R_CUTTER * Math.sin(a1)},
{x: mx + PARAMS.R_CUTTER * Math.cos(a2), y: my + PARAMS.R_CUTTER * Math.sin(a2)},
{x: mx + PARAMS.R_CUTTER * Math.cos(a3), y: my + PARAMS.R_CUTTER * Math.sin(a3)}
];
for(let i=0; i<3; i++) {
trailData[i].push(`${pts[i].x.toFixed(1)},${pts[i].y.toFixed(1)}`);
if(trailData[i].length > MAX_TRAIL_LEN) trailData[i].shift();
if(trailData[i].length > 1) {
trailPaths[i].setAttribute('d', 'M ' + trailData[i].join(' L '));
}
}
}
// --- UI 状态数据同步 ---
uiPhase.innerText = phase === 'DESCEND' ? '内轴进给下压' :
(phase === 'MILL' ? '高速偏心铣削中' :
(phase === 'RETRACT' ? '刀具抬起回退' : '系统待命'));
uiPhase.className = isMill ? 'val-green' : 'val-amber';
uiZDepth.innerText = (zDepth / 10).toFixed(2) + ' mm';
uiOuterState.innerText = orbitSpeed > 0 ? `匀速公转 (${PARAMS.RPM_ORBIT} RPM)` : '停止锁定';
uiOuterState.className = orbitSpeed > 0 ? 'val-cyan' : 'val-amber';
uiOrbitRpm.innerText = orbitSpeed > 0 ? `${PARAMS.RPM_ORBIT} RPM` : '0 RPM';
uiOrbitRpm.className = orbitSpeed > 0 ? 'val-cyan' : '';
uiSpinRpm.innerText = isMill ? `${PARAMS.RPM_SPIN} RPM` : '0 RPM';
uiSpinRpm.className = isMill ? 'val-cyan' : '';
// 核心IFR展示:速度对比
if (isMill) {
uiCenterSpeed.innerText = '10.05 m/s (绝对覆盖)';
uiCenterSpeed.className = 'val-green';
uiQuality.innerText = '完美弧面光洁度 (撕裂消除)';
uiQuality.className = 'val-green';
indMill.classList.add('active');
indIfr.classList.add('active');
} else {
uiCenterSpeed.innerText = '0.00 m/s (切割死角)';
uiCenterSpeed.className = 'val-red';
uiQuality.innerText = '起毛/撕裂风险极高';
uiQuality.className = 'val-red';
indMill.classList.remove('active');
indIfr.classList.remove('active');
}
indPower.classList.add('active');
requestAnimationFrame(animate);
}
function clearTrails() {
for(let i=0; i<numTrails; i++) {
trailData[i] = [];
trailPaths[i].setAttribute('d', '');
}
}
// 页面加载完成后自动执行,无需用户干预
window.addEventListener('DOMContentLoaded', () => {
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
