<!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>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
:root {
--bg: #060a12;
--panel: rgba(10,18,32,0.92);
--border: rgba(0,229,255,0.15);
--accent: #00e5ff;
--accent2: #ff6d00;
--accent3: #00e676;
--text: #c8d6e5;
--muted: #4a5e78;
--danger: #ff5252;
--copper: #cd7f32;
--rail: #2a3550;
}
* { margin:0; padding:0; box-sizing:border-box; }
body {
background: var(--bg);
font-family: 'JetBrains Mono', monospace;
color: var(--text);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
overflow-x: hidden;
}
.main-title {
font-family: 'Orbitron', sans-serif;
font-weight: 900;
font-size: 1.3rem;
letter-spacing: 0.15em;
color: var(--accent);
text-transform: uppercase;
margin: 18px 0 4px;
text-shadow: 0 0 24px rgba(0,229,255,0.35);
}
.sub-title {
font-size: 0.72rem;
color: var(--muted);
letter-spacing: 0.08em;
margin-bottom: 10px;
}
.svg-wrap {
width: 96vw;
max-width: 1440px;
aspect-ratio: 16/9;
position: relative;
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
background: linear-gradient(180deg, #080e1a 0%, #0b1220 60%, #0d1528 100%);
box-shadow: 0 0 60px rgba(0,229,255,0.06), inset 0 0 80px rgba(0,0,0,0.4);
}
.svg-wrap svg { width:100%; height:100%; display:block; }
.controls {
display: flex;
gap: 16px;
flex-wrap: wrap;
align-items: center;
justify-content: center;
margin: 14px 0 20px;
padding: 12px 24px;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 10px;
}
.ctrl-group {
display: flex;
align-items: center;
gap: 8px;
}
.ctrl-label {
font-size: 0.68rem;
color: var(--muted);
letter-spacing: 0.06em;
text-transform: uppercase;
white-space: nowrap;
}
.ctrl-value {
font-size: 0.72rem;
color: var(--accent);
min-width: 52px;
text-align: right;
font-weight: 700;
}
button {
font-family: 'Orbitron', sans-serif;
font-size: 0.65rem;
letter-spacing: 0.1em;
padding: 6px 16px;
border: 1px solid var(--accent);
background: rgba(0,229,255,0.08);
color: var(--accent);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
text-transform: uppercase;
}
button:hover { background: rgba(0,229,255,0.2); box-shadow: 0 0 12px rgba(0,229,255,0.3); }
button:active { transform: scale(0.96); }
button.active { background: rgba(0,229,255,0.25); box-shadow: 0 0 16px rgba(0,229,255,0.4); }
button.orange { border-color: var(--accent2); color: var(--accent2); background: rgba(255,109,0,0.08); }
button.orange:hover { background: rgba(255,109,0,0.2); box-shadow: 0 0 12px rgba(255,109,0,0.3); }
button.green { border-color: var(--accent3); color: var(--accent3); background: rgba(0,230,118,0.08); }
button.green:hover { background: rgba(0,230,118,0.2); box-shadow: 0 0 12px rgba(0,230,118,0.3); }
input[type=range] {
-webkit-appearance: none;
width: 120px;
height: 4px;
background: var(--muted);
border-radius: 2px;
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--accent);
cursor: pointer;
box-shadow: 0 0 8px rgba(0,229,255,0.5);
}
@keyframes pulseGlow {
0%,100% { opacity:0.6; }
50% { opacity:1; }
}
@keyframes dashFlow {
to { stroke-dashoffset: -20; }
}
@media (max-width: 768px) {
.main-title { font-size: 0.95rem; }
.controls { padding: 8px 12px; gap: 8px; }
input[type=range] { width: 80px; }
}
</style>
</head>
<body>
<div class="main-title">IFR 原理动画 — 场控减振与直驱定位</div>
<div class="sub-title">电磁涡流阻尼器 & 音圈电机直驱系统 · 最终理想解可视化</div>
<div class="svg-wrap">
<svg id="mainSvg" viewBox="0 0 1400 800" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 网格图案 -->
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="rgba(0,229,255,0.04)" stroke-width="0.5"/>
</pattern>
<!-- 发光滤镜 -->
<filter id="glowCyan" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowOrange" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="5" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="glowGreen" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="softGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- 涡流渐变 -->
<radialGradient id="eddyGrad" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#00e5ff" stop-opacity="0.6"/>
<stop offset="70%" stop-color="#00bcd4" stop-opacity="0.2"/>
<stop offset="100%" stop-color="#006064" stop-opacity="0"/>
</radialGradient>
<!-- 磁铁渐变 N极 -->
<linearGradient id="magN" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#ff5252"/>
<stop offset="100%" stop-color="#b71c1c"/>
</linearGradient>
<!-- 磁铁渐变 S极 -->
<linearGradient id="magS" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#448aff"/>
<stop offset="100%" stop-color="#1565c0"/>
</linearGradient>
<!-- 轨道侧面渐变 -->
<linearGradient id="railSide" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#37474f"/>
<stop offset="100%" stop-color="#1a2530"/>
</linearGradient>
<!-- 箭头标记 -->
<marker id="arrowCyan" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#00e5ff"/>
</marker>
<marker id="arrowOrange" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#ff6d00"/>
</marker>
<marker id="arrowGreen" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#00e676"/>
</marker>
<!-- 噪声纹理 -->
<filter id="noiseFilter">
<feTurbulence type="fractalNoise" baseFrequency="0.65" numOctaves="3" stitchTiles="stitch"/>
<feColorMatrix type="saturate" values="0"/>
</filter>
</defs>
<!-- 背景网格 -->
<rect width="1400" height="800" fill="url(#grid)"/>
<!-- 噪声纹理叠加 -->
<rect width="1400" height="800" filter="url(#noiseFilter)" opacity="0.025"/>
<!-- ============ 轨道系统 ============ -->
<g id="railSystem">
<!-- 轨道顶面 -->
<rect x="0" y="460" width="1400" height="10" fill="#455a64" rx="1"/>
<!-- 轨道侧面(涡流作用面)-->
<rect x="0" y="470" width="1400" height="40" fill="url(#railSide)"/>
<!-- 轨道底面 -->
<rect x="0" y="510" width="1400" height="6" fill="#263238" rx="1"/>
<!-- 轨道接缝 -->
<g id="railJoints" fill="none" stroke="#0d1520" stroke-width="2.5">
<line x1="350" y1="460" x2="350" y2="516"/>
<line x1="700" y1="460" x2="700" y2="516"/>
<line x1="1050" y1="460" x2="1050" y2="516"/>
</g>
<!-- 轨道标签 -->
<text x="60" y="540" fill="#37474f" font-size="11" font-family="JetBrains Mono" letter-spacing="0.1em">RAIL · 导轨</text>
</g>
<!-- ============ 涡流效果层 ============ -->
<g id="eddyLayer"></g>
<!-- ============ 磁场线层 ============ -->
<g id="fieldLineLayer"></g>
<!-- ============ 穿梭车组 ============ -->
<g id="shuttleGroup">
<!-- 车体主结构 -->
<rect id="shuttleBody" x="0" y="345" width="240" height="112" rx="8" fill="#151e2e" stroke="#263850" stroke-width="1.5"/>
<!-- 车体装饰线 -->
<line x1="12" y1="370" x2="228" y2="370" stroke="#1e3048" stroke-width="1"/>
<line x1="12" y1="430" x2="228" y2="430" stroke="#1e3048" stroke-width="1"/>
<!-- 车体中心标签 -->
<text x="120" y="396" text-anchor="middle" fill="#3a5068" font-size="10" font-family="Orbitron" letter-spacing="0.15em">SHUTTLE</text>
<text x="120" y="416" text-anchor="middle" fill="#2a3e55" font-size="8" font-family="JetBrains Mono">穿梭车体</text>
<!-- 伺服驱动轮 -->
<g id="wheelGroup">
<!-- 驱动轮1 -->
<circle cx="55" cy="458" r="18" fill="#263238" stroke="#455a64" stroke-width="2"/>
<circle cx="55" cy="458" r="10" fill="#1a2530" stroke="#37474f" stroke-width="1"/>
<line cx="55" cy="458" x1="55" y1="448" x2="55" y2="468" stroke="#546e7a" stroke-width="1" id="spoke1"/>
<!-- 驱动轮2 -->
<circle cx="185" cy="458" r="18" fill="#263238" stroke="#455a64" stroke-width="2"/>
<circle cx="185" cy="458" r="10" fill="#1a2530" stroke="#37474f" stroke-width="1"/>
<line x1="185" y1="448" x2="185" y2="468" stroke="#546e7a" stroke-width="1" id="spoke2"/>
</g>
<!-- 同步带 -->
<rect x="55" y="450" width="130" height="4" fill="#37474f" rx="2" opacity="0.5"/>
<!-- 伺服电机指示 -->
<rect x="100" y="440" width="30" height="14" rx="3" fill="#1a2530" stroke="#ff6d00" stroke-width="0.8" opacity="0.7"/>
<text x="115" y="450" text-anchor="middle" fill="#ff6d00" font-size="6" font-family="JetBrains Mono">SERVO</text>
<!-- 侧向永磁体 - 左 -->
<g id="magnetLeft">
<rect x="35" y="462" width="12" height="28" rx="2" fill="url(#magN)"/>
<text x="41" y="480" text-anchor="middle" fill="#ffcdd2" font-size="8" font-weight="700" font-family="JetBrains Mono">N</text>
<rect x="47" y="462" width="12" height="28" rx="2" fill="url(#magS)"/>
<text x="53" y="480" text-anchor="middle" fill="#bbdefb" font-size="8" font-weight="700" font-family="JetBrains Mono">S</text>
</g>
<!-- 侧向永磁体 - 右 -->
<g id="magnetRight">
<rect x="165" y="462" width="12" height="28" rx="2" fill="url(#magN)"/>
<text x="171" y="480" text-anchor="middle" fill="#ffcdd2" font-size="8" font-weight="700" font-family="JetBrains Mono">N</text>
<rect x="177" y="462" width="12" height="28" rx="2" fill="url(#magS)"/>
<text x="183" y="480" text-anchor="middle" fill="#bbdefb" font-size="8" font-weight="700" font-family="JetBrains Mono">S</text>
</g>
<!-- 间隙标注 -->
<g id="gapAnnotation" opacity="0">
<line x1="59" y1="475" x2="59" y2="475" stroke="#00e5ff" stroke-width="0.8" stroke-dasharray="2,2"/>
<text x="70" y="498" fill="#00e5ff" font-size="9" font-family="JetBrains Mono" opacity="0.9">0.5mm</text>
<line x1="59" y1="490" x2="59" y2="470" stroke="#00e5ff" stroke-width="0.6" stroke-dasharray="3,2"/>
<!-- 间隙指示线 -->
<line x1="59" y1="470" x2="59" y2="470" stroke="#00e5ff" stroke-width="0.5"/>
</g>
<!-- ============ 音圈电机 & 货叉 ============ -->
<g id="vcmGroup">
<!-- VCM外壳 -->
<rect x="220" y="365" width="60" height="70" rx="4" fill="#1a1a2e" stroke="#cd7f32" stroke-width="1.2"/>
<!-- VCM线圈 -->
<rect id="vcmCoil" x="228" y="373" width="44" height="54" rx="3" fill="none" stroke="#cd7f32" stroke-width="2" opacity="0.7"/>
<!-- VCM永磁体 -->
<rect x="232" y="377" width="8" height="46" rx="1" fill="url(#magN)" opacity="0.8"/>
<rect x="260" y="377" width="8" height="46" rx="1" fill="url(#magS)" opacity="0.8"/>
<!-- VCM标签 -->
<text x="250" y="400" text-anchor="middle" fill="#cd7f32" font-size="7" font-family="Orbitron" letter-spacing="0.08em">VCM</text>
<!-- VCM力箭头层 -->
<g id="vcmForceLayer"></g>
</g>
<!-- 货叉 -->
<g id="forkGroup">
<!-- 货叉主体 -->
<rect id="forkBody" x="280" y="380" width="0" height="40" rx="3" fill="#5d4037" stroke="#8d6e63" stroke-width="1"/>
<!-- 货叉尖端 -->
<g id="forkTip" opacity="0">
<polygon points="0,380 20,390 0,400 6,395 6,385" fill="#8d6e63"/>
</g>
<!-- 货叉标签 -->
<g id="forkLabel" opacity="0">
<text x="0" y="374" fill="#8d6e63" font-size="8" font-family="JetBrains Mono">FORK</text>
</g>
</g>
</g>
<!-- ============ 目标料箱 ============ -->
<g id="targetBin" opacity="0">
<rect x="0" y="355" width="50" height="80" rx="3" fill="none" stroke="#00e676" stroke-width="1.5" stroke-dasharray="6,3"/>
<rect x="0" y="375" width="50" height="40" rx="2" fill="rgba(0,230,118,0.06)"/>
<text x="25" y="400" text-anchor="middle" fill="#00e676" font-size="8" font-family="JetBrains Mono" opacity="0.7">目标孔</text>
</g>
<!-- ============ 阻尼力指示 ============ -->
<g id="dampingForceLayer"></g>
<!-- ============ 振动指示层 ============ -->
<g id="vibrationLayer"></g>
<!-- ============ 信息面板 ============ -->
<g id="infoPanel">
<!-- 阶段指示 -->
<rect x="30" y="20" width="260" height="44" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(0,229,255,0.2)" stroke-width="1"/>
<text x="42" y="38" fill="#4a5e78" font-size="9" font-family="JetBrains Mono" letter-spacing="0.08em">PHASE</text>
<text id="phaseText" x="42" y="54" fill="#00e5ff" font-size="13" font-family="Orbitron" font-weight="700" letter-spacing="0.1em">STANDBY</text>
<!-- 参数面板 -->
<rect x="30" y="76" width="260" height="160" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(0,229,255,0.12)" stroke-width="1"/>
<text x="42" y="96" fill="#4a5e78" font-size="9" font-family="JetBrains Mono" letter-spacing="0.1em">PARAMETERS</text>
<text x="42" y="118" fill="#607d8b" font-size="9" font-family="JetBrains Mono">直行速度</text>
<text id="paramSpeed" x="248" y="118" text-anchor="end" fill="#00e5ff" font-size="11" font-family="JetBrains Mono" font-weight="700">0.0 m/s</text>
<text x="42" y="138" fill="#607d8b" font-size="9" font-family="JetBrains Mono">涡流阻尼力</text>
<text id="paramDamping" x="248" y="138" text-anchor="end" fill="#00e5ff" font-size="11" font-family="JetBrains Mono" font-weight="700">0 N</text>
<text x="42" y="158" fill="#607d8b" font-size="9" font-family="JetBrains Mono">叉速</text>
<text id="paramForkSpeed" x="248" y="158" text-anchor="end" fill="#ff6d00" font-size="11" font-family="JetBrains Mono" font-weight="700">0.0 m/s</text>
<text x="42" y="178" fill="#607d8b" font-size="9" font-family="JetBrains Mono">VCM推力</text>
<text id="paramVcmForce" x="248" y="178" text-anchor="end" fill="#ff6d00" font-size="11" font-family="JetBrains Mono" font-weight="700">0 N</text>
<text x="42" y="198" fill="#607d8b" font-size="9" font-family="JetBrains Mono">VCM电流</text>
<text id="paramVcmCurrent" x="248" y="198" text-anchor="end" fill="#cd7f32" font-size="11" font-family="JetBrains Mono" font-weight="700">0.0 A</text>
<text x="42" y="218" fill="#607d8b" font-size="9" font-family="JetBrains Mono">车体振幅</text>
<text id="paramVibration" x="248" y="218" text-anchor="end" fill="#ff5252" font-size="11" font-family="JetBrains Mono" font-weight="700">0.0 mm</text>
</g>
<!-- ============ IFR 原理说明 ============ -->
<g id="ifrPanel">
<rect x="1100" y="20" width="270" height="100" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(0,230,118,0.2)" stroke-width="1"/>
<text x="1112" y="40" fill="#00e676" font-size="9" font-family="Orbitron" font-weight="700" letter-spacing="0.12em">IFR · 最终理想解</text>
<text x="1112" y="58" fill="#78909c" font-size="8.5" font-family="JetBrains Mono">以场代实 · 非接触阻尼</text>
<text x="1112" y="74" fill="#78909c" font-size="8.5" font-family="JetBrains Mono">洛伦兹力 · 毫秒级响应</text>
<text x="1112" y="90" fill="#546e7a" font-size="7.5" font-family="JetBrains Mono">无磨损 · 无润滑 · 零接触</text>
<text x="1112" y="108" fill="#37474f" font-size="7" font-family="JetBrains Mono">场控代替机械传动</text>
</g>
<!-- ============ 电流波形显示 ============ -->
<g id="waveformPanel">
<rect x="1100" y="132" width="270" height="105" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(205,127,50,0.2)" stroke-width="1"/>
<text x="1112" y="150" fill="#cd7f32" font-size="9" font-family="Orbitron" font-weight="700" letter-spacing="0.1em">VCM CURRENT WAVEFORM</text>
<!-- 波形画布 -->
<rect x="1112" y="158" width="246" height="68" rx="3" fill="rgba(0,0,0,0.3)"/>
<line x1="1112" y1="192" x2="1358" y2="192" stroke="#1a2530" stroke-width="0.5"/>
<path id="waveformPath" d="" fill="none" stroke="#cd7f32" stroke-width="1.5" filter="url(#softGlow)"/>
</g>
<!-- ============ 涡流阻尼详情 ============ -->
<g id="eddyDetailPanel">
<rect x="1100" y="250" width="270" height="130" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(0,229,255,0.15)" stroke-width="1"/>
<text x="1112" y="270" fill="#00e5ff" font-size="9" font-family="Orbitron" font-weight="700" letter-spacing="0.1em">EDDY CURRENT DAMPER</text>
<!-- 涡流示意 -->
<g transform="translate(1140,300)">
<!-- 轨道截面 -->
<rect x="0" y="20" width="80" height="50" rx="2" fill="#263238" stroke="#37474f" stroke-width="1"/>
<text x="40" y="50" text-anchor="middle" fill="#455a64" font-size="7" font-family="JetBrains Mono">轨道侧面</text>
<!-- 永磁体 -->
<rect x="88" y="28" width="20" height="34" rx="2" fill="url(#magN)"/>
<rect x="108" y="28" width="20" height="34" rx="2" fill="url(#magS)"/>
<text x="98" y="49" text-anchor="middle" fill="#ffcdd2" font-size="7" font-weight="700" font-family="JetBrains Mono">N</text>
<text x="118" y="49" text-anchor="middle" fill="#bbdefb" font-size="7" font-weight="700" font-family="JetBrains Mono">S</text>
<!-- 间隙标注 -->
<line x1="80" y1="32" x2="88" y2="32" stroke="#00e5ff" stroke-width="0.8"/>
<line x1="80" y1="58" x2="88" y2="58" stroke="#00e5ff" stroke-width="0.8"/>
<text x="84" y="26" text-anchor="middle" fill="#00e5ff" font-size="7" font-family="JetBrains Mono">0.5mm</text>
<!-- 涡流环 -->
<g id="eddyDetailSwirls" opacity="0.6">
<circle cx="30" cy="42" r="10" fill="none" stroke="#00e5ff" stroke-width="1" stroke-dasharray="4,3" opacity="0.7">
<animateTransform attributeName="transform" type="rotate" from="0 30 42" to="360 30 42" dur="1.5s" repeatCount="indefinite"/>
</circle>
<circle cx="55" cy="48" r="8" fill="none" stroke="#00e5ff" stroke-width="1" stroke-dasharray="3,3" opacity="0.5">
<animateTransform attributeName="transform" type="rotate" from="360 55 48" to="0 55 48" dur="2s" repeatCount="indefinite"/>
</circle>
</g>
<!-- 磁力线 -->
<path d="M88 35 Q78 35 78 45 Q78 55 88 55" fill="none" stroke="#00bcd4" stroke-width="0.8" stroke-dasharray="3,2" opacity="0.6">
<animate attributeName="stroke-dashoffset" from="0" to="-10" dur="0.8s" repeatCount="indefinite"/>
</path>
<path d="M108 35 Q98 35 98 45 Q98 55 108 55" fill="none" stroke="#00bcd4" stroke-width="0.8" stroke-dasharray="3,2" opacity="0.5">
<animate attributeName="stroke-dashoffset" from="0" to="-10" dur="0.8s" repeatCount="indefinite"/>
</path>
</g>
<!-- 说明文字 -->
<text x="1112" y="366" fill="#546e7a" font-size="7.5" font-family="JetBrains Mono">阻尼力 ∝ 振动速度</text>
<text x="1112" y="378" fill="#37474f" font-size="7" font-family="JetBrains Mono">高速强阻尼 · 低速自然衰减</text>
</g>
<!-- ============ 洛伦兹力公式 ============ -->
<g id="lorentzPanel">
<rect x="1100" y="394" width="270" height="76" rx="6" fill="rgba(6,10,18,0.85)" stroke="rgba(255,109,0,0.15)" stroke-width="1"/>
<text x="1112" y="414" fill="#ff6d00" font-size="9" font-family="Orbitron" font-weight="700" letter-spacing="0.1em">LORENTZ FORCE</text>
<text x="1235" y="442" text-anchor="middle" fill="#ffab00" font-size="16" font-family="JetBrains Mono" font-weight="700">F = BIL</text>
<text x="1112" y="460" fill="#546e7a" font-size="7.5" font-family="JetBrains Mono">推力≥500N · 加速度≥10m/s²</text>
</g>
<!-- ============ 动态标注层 ============ -->
<g id="annotationLayer"></g>
</svg>
</div>
<!-- 控制面板 -->
<div class="controls">
<div class="ctrl-group">
<button id="btnPlay" class="active">AUTO PLAY</button>
<button id="btnReset">RESET</button>
</div>
<div class="ctrl-group">
<span class="ctrl-label">速度倍率</span>
<input type="range" id="speedMul" min="0.3" max="2" step="0.1" value="1">
<span class="ctrl-value" id="speedMulVal">1.0x</span>
</div>
<div class="ctrl-group">
<button id="btnManual" class="orange">MANUAL</button>
</div>
<div class="ctrl-group" id="manualControls" style="display:none;">
<span class="ctrl-label">车速度</span>
<input type="range" id="manualSpeed" min="0" max="5" step="0.1" value="0">
<span class="ctrl-value" id="manualSpeedVal">0.0</span>
<span class="ctrl-label">叉行程</span>
<input type="range" id="manualFork" min="0" max="100" step="1" value="0">
<span class="ctrl-value" id="manualForkVal">0%</span>
</div>
</div>
<script>
// ============================
// 动画引擎
// ============================
const SVG_NS = 'http://www.w3.org/2000/svg';
const svg = document.getElementById('mainSvg');
// 获取关键DOM元素
const shuttleGroup = document.getElementById('shuttleGroup');
const forkBody = document.getElementById('forkBody');
const forkTip = document.getElementById('forkTip');
const forkLabel = document.getElementById('forkLabel');
const targetBin = document.getElementById('targetBin');
const gapAnnotation = document.getElementById('gapAnnotation');
const eddyLayer = document.getElementById('eddyLayer');
const fieldLineLayer = document.getElementById('fieldLineLayer');
const dampingForceLayer = document.getElementById('dampingForceLayer');
const vibrationLayer = document.getElementById('vibrationLayer');
const vcmForceLayer = document.getElementById('vcmForceLayer');
const vcmCoil = document.getElementById('vcmCoil');
const annotationLayer = document.getElementById('annotationLayer');
const waveformPath = document.getElementById('waveformPath');
const spoke1 = document.getElementById('spoke1');
const spoke2 = document.getElementById('spoke2');
// 参数显示元素
const paramSpeed = document.getElementById('paramSpeed');
const paramDamping = document.getElementById('paramDamping');
const paramForkSpeed = document.getElementById('paramForkSpeed');
const paramVcmForce = document.getElementById('paramVcmForce');
const paramVcmCurrent = document.getElementById('paramVcmCurrent');
const paramVibration = document.getElementById('paramVibration');
const phaseText = document.getElementById('phaseText');
// 控制元素
const btnPlay = document.getElementById('btnPlay');
const btnReset = document.getElementById('btnReset');
const btnManual = document.getElementById('btnManual');
const speedMulSlider = document.getElementById('speedMul');
const speedMulVal = document.getElementById('speedMulVal');
const manualControls = document.getElementById('manualControls');
const manualSpeedSlider = document.getElementById('manualSpeed');
const manualSpeedVal = document.getElementById('manualSpeedVal');
const manualForkSlider = document.getElementById('manualFork');
const manualForkVal = document.getElementById('manualForkVal');
// ============================
// 动画状态
// ============================
let state = {
mode: 'auto', // 'auto' | 'manual'
phase: 0, // 0:待机 1:高速直行 2:减速 3:伸叉 4:柔性制动 5:完成
time: 0,
shuttleX: 80,
shuttleSpeed: 0, // m/s
vibration: 0, // 振幅 mm
vibrationPhase: 0,
dampingForce: 0, // N
forkExtension: 0, // 0~1
forkSpeed: 0, // m/s
vcmForce: 0, // N
vcmCurrent: 0, // A
eddyIntensity: 0, // 0~1
speedMul: 1,
running: true,
wheelAngle: 0,
// 涡流圆环
eddyCircles: [],
// 波形历史
waveformHistory: [],
// 磁场线
fieldLines: [],
// 动态标注
annotations: []
};
// 阶段配置
const PHASES = [
{ name: 'STANDBY', duration: 1.5, label: '系统待机' },
{ name: 'HIGH-SPEED', duration: 4, label: '高速直行 5m/s' },
{ name: 'DECELERATE', duration: 1.5, label: '减速停靠' },
{ name: 'FORK-EXTEND', duration: 2, label: '音圈电机伸叉' },
{ name: 'SOFT-BRAKE', duration: 1.8, label: '柔性制动对接' },
{ name: 'COMPLETE', duration: 2, label: '对接完成' }
];
// ============================
// 工具函数
// ============================
function lerp(a, b, t) { return a + (b - a) * Math.max(0, Math.min(1, t)); }
function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }
function easeInOut(t) { return t < 0.5 ? 2*t*t : -1+(4-2*t)*t; }
function easeOut(t) { return 1 - Math.pow(1 - t, 3); }
function easeIn(t) { return t * t * t; }
// 创建SVG元素
function createSvgEl(tag, attrs) {
const el = document.createElementNS(SVG_NS, tag);
for (const [k, v] of Object.entries(attrs)) {
el.setAttribute(k, v);
}
return el;
}
// ============================
// 涡流效果管理
// ============================
const MAX_EDDY_CIRCLES = 12;
function initEddyCircles() {
for (let i = 0; i < MAX_EDDY_CIRCLES; i++) {
const circle = createSvgEl('ellipse', {
cx: 0, cy: 0, rx: 8, ry: 5,
fill: 'none',
stroke: '#00e5ff',
'stroke-width': '1.2',
'stroke-dasharray': '4,3',
opacity: 0
});
circle.style.transformOrigin = 'center';
eddyLayer.appendChild(circle);
state.eddyCircles.push({ el: circle, active: false, x: 0, y: 0, rot: 0, life: 0 });
}
}
function updateEddyCircles(dt, shuttleScreenX) {
const intensity = state.eddyIntensity;
// 在轨道侧面上生成涡流效果
const railY = 485; // 轨道侧面中心Y
// 根据强度激活/管理涡流圆
for (let i = 0; i < state.eddyCircles.length; i++) {
const ec = state.eddyCircles[i];
if (intensity > 0.1 && !ec.active && Math.random() < intensity * dt * 3) {
// 激活一个涡流圆
const magnetOffsetX = (i % 2 === 0) ? 47 : 183; // 左磁体或右磁体
ec.x = shuttleScreenX + magnetOffsetX + (Math.random() - 0.5) * 30;
ec.y = railY + (Math.random() - 0.5) * 20;
ec.active = true;
ec.life = 1;
ec.rot = Math.random() * 360;
const scale = 0.5 + Math.random() * 0.8;
ec.el.setAttribute('rx', 8 * scale);
ec.el.setAttribute('ry', 5 * scale);
}
if (ec.active) {
ec.life -= dt * (0.8 + intensity * 0.5);
ec.rot += dt * (120 + intensity * 200) * (i % 2 === 0 ? 1 : -1);
if (ec.life <= 0) {
ec.active = false;
ec.el.setAttribute('opacity', 0);
} else {
ec.el.setAttribute('cx', ec.x);
ec.el.setAttribute('cy', ec.y);
ec.el.setAttribute('opacity', ec.life * intensity * 0.7);
ec.el.setAttribute('transform', `rotate(${ec.rot} ${ec.x} ${ec.y})`);
}
}
}
}
// ============================
// 磁场线管理
// ============================
function updateFieldLines(dt, shuttleScreenX) {
// 清除旧的磁场线
while (fieldLineLayer.firstChild) fieldLineLayer.removeChild(fieldLineLayer.firstChild);
const intensity = state.eddyIntensity;
if (intensity < 0.05) return;
const railTop = 470;
const magnetY = 475;
// 左磁体磁场线
const magPositions = [shuttleScreenX + 47, shuttleScreenX + 183];
magPositions.forEach((mx, idx) => {
for (let i = 0; i < 3; i++) {
const spread = (i - 1) * 6;
const path = createSvgEl('path', {
d: `M${mx + spread} ${magnetY} Q${mx + spread - 8 - i*3} ${magnetY - 12 - i*4} ${mx + spread} ${railTop}`,
fill: 'none',
stroke: '#00bcd4',
'stroke-width': 0.8,
'stroke-dasharray': '3,3',
opacity: intensity * 0.5 * (1 - i * 0.2)
});
// 动画dashoffset
const anim = createSvgEl('animate', {
attributeName: 'stroke-dashoffset',
from: '0', to: '-12', dur: `${0.6 + i * 0.2}s`,
repeatCount: 'indefinite'
});
path.appendChild(anim);
fieldLineLayer.appendChild(path);
}
});
}
// ============================
// VCM力箭头管理
// ============================
function updateVcmForces(shuttleScreenX) {
while (vcmForceLayer.firstChild) vcmForceLayer.removeChild(vcmForceLayer.firstChild);
const force = state.vcmForce;
if (Math.abs(force) < 5) return;
const vcmCenterX = shuttleScreenX + 250;
const vcmCenterY = 400;
const arrowLen = clamp(Math.abs(force) / 500 * 50, 10, 60);
const dir = force > 0 ? 1 : -1;
const color = Math.abs(force) > 300 ? '#ff6d00' : '#ffab00';
// 主力箭头
const arrow = createSvgEl('line', {
x1: vcmCenterX, y1: vcmCenterY,
x2: vcmCenterX + arrowLen * dir, y2: vcmCenterY,
stroke: color, 'stroke-width': 3,
'marker-end': 'url(#arrowOrange)',
opacity: 0.9,
filter: 'url(#glowOrange)'
});
vcmForceLayer.appendChild(arrow);
// 力值标注
const label = createSvgEl('text', {
x: vcmCenterX + arrowLen * dir * 0.5,
y: vcmCenterY - 12,
'text-anchor': 'middle',
fill: color,
'font-size': 10,
'font-family': 'JetBrains Mono',
'font-weight': 700
});
label.textContent = `${Math.abs(force).toFixed(0)}N`;
vcmForceLayer.appendChild(label);
}
// ============================
// 阻尼力指示
// ============================
function updateDampingForces(shuttleScreenX) {
while (dampingForceLayer.firstChild) dampingForceLayer.removeChild(dampingForceLayer.firstChild);
const force = state.dampingForce;
if (force < 2) return;
const arrowLen = clamp(force / 200 * 35, 8, 40);
// 左磁体阻尼力箭头(向上,表示抑制振动)
[shuttleScreenX + 47, shuttleScreenX + 183].forEach(mx => {
const arrow = createSvgEl('line', {
x1: mx, y1: 462,
x2: mx, y2: 462 - arrowLen,
stroke: '#00e5ff', 'stroke-width': 2.5,
'marker-end': 'url(#arrowCyan)',
opacity: 0.7,
filter: 'url(#glowCyan)'
});
dampingForceLayer.appendChild(arrow);
});
// 阻尼力值
const label = createSvgEl('text', {
x: shuttleScreenX + 115,
y: 450 - arrowLen,
'text-anchor': 'middle',
fill: '#00e5ff',
'font-size': 9,
'font-family': 'JetBrains Mono',
'font-weight': 700,
opacity: 0.8
});
label.textContent = `阻尼 ${force.toFixed(0)}N`;
dampingForceLayer.appendChild(label);
}
// ============================
// 振动效果
// ============================
function updateVibration(dt) {
while (vibrationLayer.firstChild) vibrationLayer.removeChild(vibrationLayer.firstChild);
const vib = state.vibration;
if (vib < 0.3) return;
// 振动波形线(在车体两侧显示)
const shuttleScreenX = state.shuttleX;
const points = [];
for (let i = 0; i < 20; i++) {
const x = shuttleScreenX + 10 + i * 11;
const y = 340 + Math.sin(state.vibrationPhase + i * 0.8) * vib * 1.5;
points.push(`${x},${y}`);
}
const waveLine = createSvgEl('polyline', {
points: points.join(' '),
fill: 'none',
stroke: '#ff5252',
'stroke-width': 1.2,
opacity: clamp(vib / 5, 0.2, 0.8)
});
vibrationLayer.appendChild(waveLine);
// 振幅标注
if (vib > 1) {
const vLabel = createSvgEl('text', {
x: shuttleScreenX + 120,
y: 332,
'text-anchor': 'middle',
fill: '#ff5252',
'font-size': 9,
'font-family': 'JetBrains Mono',
opacity: 0.7
});
vLabel.textContent = `振幅 ${vib.toFixed(1)}mm`;
vibrationLayer.appendChild(vLabel);
}
}
// ============================
// 波形显示
// ============================
function updateWaveform() {
state.waveformHistory.push(state.vcmCurrent);
if (state.waveformHistory.length > 120) state.waveformHistory.shift();
if (state.waveformHistory.length < 2) return;
const baseX = 1114;
const baseY = 192;
const width = 242;
const height = 30;
const step = width / 120;
let d = '';
state.waveformHistory.forEach((v, i) => {
const x = baseX + i * step;
const y = baseY - (v / 50) * height;
d += (i === 0 ? 'M' : 'L') + `${x},${y}`;
});
waveformPath.setAttribute('d', d);
}
// ============================
// 动态标注
// ============================
function updateAnnotations() {
while (annotationLayer.firstChild) annotationLayer.removeChild(annotationLayer.firstChild);
const sx = state.shuttleX;
// 阶段2+:间隙标注
if (state.phase >= 1 && state.phase <= 2 && state.shuttleSpeed > 0.5) {
gapAnnotation.setAttribute('opacity', clamp(state.eddyIntensity, 0, 1));
} else {
gapAnnotation.setAttribute('opacity', 0);
}
// 阶段3-4:VCM标注
if (state.phase >= 3 && state.phase <= 4) {
// 推力标注
const tLabel = createSvgEl('text', {
x: sx + 250, y: 356,
'text-anchor': 'middle',
fill: '#ff6d00',
'font-size': 9,
'font-family': 'JetBrains Mono',
opacity: 0.8
});
tLabel.textContent = state.phase === 3 ? '爆发推力' : '柔性制动';
annotationLayer.appendChild(tLabel);
}
// 阶段1:速度标注
if (state.phase === 1 && state.shuttleSpeed > 2) {
const sLabel = createSvgEl('text', {
x: sx + 120, y: 330,
'text-anchor': 'middle',
fill: '#00e5ff',
'font-size': 11,
'font-family': 'Orbitron',
'font-weight': 700,
opacity: 0.6,
filter: 'url(#softGlow)'
});
sLabel.textContent = `→ ${state.shuttleSpeed.toFixed(1)} m/s`;
annotationLayer.appendChild(sLabel);
}
}
// ============================
// 主动画更新
// ============================
function updateAutoPhase(dt) {
const p = state.phase;
const t = state.time;
const cfg = PHASES[p] || PHASES[0];
const progress = clamp(t / cfg.duration, 0, 1);
switch (p) {
case 0: // 待机
state.shuttleSpeed = 0;
state.vibration = 0;
state.dampingForce = 0;
state.forkExtension = 0;
state.forkSpeed = 0;
state.vcmForce = 0;
state.vcmCurrent = 0;
state.eddyIntensity = 0;
break;
case 1: { // 高速直行
const accelT = clamp(t / 1.0, 0, 1);
state.shuttleSpeed = easeOut(accelT) * 5;
// 无阻尼时的振幅较大,有阻尼时被抑制
const rawVibration = state.shuttleSpeed * 1.2; // 无阻尼振幅
const dampedVibration = rawVibration * (1 - state.eddyIntensity * 0.92);
state.vibration = lerp(state.vibration, dampedVibration, dt * 3);
// 涡流阻尼力与速度成正比
state.eddyIntensity = clamp(state.shuttleSpeed / 5, 0, 1);
state.dampingForce = state.eddyIntensity * 180;
break;
}
case 2: { // 减速
const decelProgress = easeInOut(progress);
state.shuttleSpeed = lerp(5, 0, decelProgress);
state.eddyIntensity = clamp(state.shuttleSpeed / 5, 0, 1);
state.dampingForce = state.eddyIntensity * 180;
state.vibration = lerp(state.vibration, state.shuttleSpeed * 0.15, dt * 4);
// 极低速时显示机械导向提示
if (state.shuttleSpeed < 0.5 && state.shuttleSpeed > 0.05) {
state.dampingForce = 0;
}
break;
}
case 3: { // 音圈电机伸叉
state.shuttleSpeed = 0;
state.eddyIntensity = lerp(state.eddyIntensity, 0, dt * 2);
state.dampingForce = 0;
state.vibration = lerp(state.vibration, 0, dt * 3);
const extendProgress = easeIn(clamp(progress * 1.2, 0, 1));
state.forkExtension = extendProgress;
state.forkSpeed = progress < 0.8 ? 1.0 : lerp(1.0, 0.3, (progress - 0.8) / 0.2);
state.vcmForce = progress < 0.8 ? 500 : lerp(500, 200, (progress - 0.8) / 0.2);
state.vcmCurrent = state.vcmForce / 20; // 简化
break;
}
case 4: { // 柔性制动
const brakeProgress = easeOut(progress);
state.forkExtension = lerp(state.forkExtension, 1, dt * 1.5);
state.forkSpeed = lerp(state.forkSpeed, 0, dt * 2);
state.vcmForce = lerp(state.vcmForce, 0, dt * 2);
state.vcmCurrent = lerp(state.vcmCurrent, 0, dt * 2.5);
// 电流波形逐渐平滑
break;
}
case 5: // 完成
state.forkExtension = 1;
state.forkSpeed = 0;
state.vcmForce = 0;
state.vcmCurrent = lerp(state.vcmCurrent, 0, dt * 3);
state.vibration = 0;
break;
}
// 更新穿梭车位置
state.shuttleX += state.shuttleSpeed * dt * 55; // 缩放到SVG坐标
// 振动相位
state.vibrationPhase += dt * 25;
// 车轮旋转
state.wheelAngle += state.shuttleSpeed * dt * 200;
// 阶段切换
if (t >= cfg.duration) {
if (p < 5) {
state.phase = p + 1;
state.time = 0;
} else {
// 循环重置
state.phase = 0;
state.time = 0;
state.shuttleX = 80;
}
}
}
function updateManualPhase(dt) {
const targetSpeed = parseFloat(manualSpeedSlider.value);
const targetFork = parseFloat(manualForkSlider.value) / 100;
state.shuttleSpeed = lerp(state.shuttleSpeed, targetSpeed, dt * 3);
state.forkExtension = lerp(state.forkExtension, targetFork, dt * 4);
state.eddyIntensity = clamp(state.shuttleSpeed / 5, 0, 1);
state.dampingForce = state.eddyIntensity * 180;
const rawVib = state.shuttleSpeed * 1.2;
state.vibration = rawVib * (1 - state.eddyIntensity * 0.92);
// VCM
if (targetFork > state.forkExtension + 0.01) {
state.vcmForce = lerp(state.vcmForce, 500, dt * 5);
state.forkSpeed = lerp(state.forkSpeed, 1, dt * 3);
} else if (targetFork < state.forkExtension - 0.01) {
state.vcmForce = lerp(state.vcmForce, -300, dt * 5);
state.forkSpeed = lerp(state.forkSpeed, -0.5, dt * 3);
} else {
state.vcmForce = lerp(state.vcmForce, 0, dt * 5);
state.forkSpeed = lerp(state.forkSpeed, 0, dt * 3);
}
state.vcmCurrent = Math.abs(state.vcmForce) / 20;
state.shuttleX += state.shuttleSpeed * dt * 55;
state.vibrationPhase += dt * 25;
state.wheelAngle += state.shuttleSpeed * dt * 200;
// 位置循环
if (state.shuttleX > 900) state.shuttleX = 80;
if (state.shuttleX < 50) state.shuttleX = 50;
}
// ============================
// 渲染
// ============================
function render() {
const sx = state.shuttleX;
const vibY = Math.sin(state.vibrationPhase) * state.vibration * 1.2;
// 穿梭车位置 + 振动偏移
shuttleGroup.setAttribute('transform', `translate(${sx}, ${vibY})`);
// 车轮旋转
const wheelRot = state.wheelAngle;
// 用spoke旋转表示车轮转动
spoke1.setAttribute('transform', `rotate(${wheelRot} 55 458)`);
spoke2.setAttribute('transform', `rotate(${wheelRot} 185 458)`);
// 货叉
const forkLen = state.forkExtension * 200;
forkBody.setAttribute('width', Math.max(0, forkLen));
forkBody.setAttribute('x', 280);
// 货叉尖端
if (forkLen > 20) {
forkTip.setAttribute('opacity', 1);
forkTip.setAttribute('transform', `translate(${280 + forkLen}, 0)`);
} else {
forkTip.setAttribute('opacity', 0);
}
// 货叉标签
if (forkLen > 30) {
forkLabel.setAttribute('opacity', 0.8);
forkLabel.setAttribute('transform', `translate(${280 + forkLen * 0.4}, 0)`);
} else {
forkLabel.setAttribute('opacity', 0);
}
// 目标料箱
if (state.phase >= 3 || (state.mode === 'manual' && state.forkExtension > 0.05)) {
targetBin.setAttribute('opacity', 1);
targetBin.setAttribute('transform', `translate(${sx + 500}, 0)`);
} else {
targetBin.setAttribute('opacity', 0);
}
// VCM线圈发光
const coilGlow = clamp(state.vcmCurrent / 25, 0, 1);
vcmCoil.setAttribute('stroke', coilGlow > 0.3 ? '#ff8f00' : '#cd7f32');
vcmCoil.setAttribute('stroke-width', 2 + coilGlow * 2);
vcmCoil.setAttribute('opacity', 0.7 + coilGlow * 0.3);
if (coilGlow > 0.3) {
vcmCoil.setAttribute('filter', 'url(#glowOrange)');
} else {
vcmCoil.removeAttribute('filter');
}
// 更新效果层
updateEddyCircles(0.016, sx);
updateFieldLines(0.016, sx);
updateVcmForces(sx);
updateDampingForces(sx);
updateVibration(0.016);
updateAnnotations();
updateWaveform();
// 更新参数显示
paramSpeed.textContent = state.shuttleSpeed.toFixed(1) + ' m/s';
paramDamping.textContent = state.dampingForce.toFixed(0) + ' N';
paramForkSpeed.textContent = state.forkSpeed.toFixed(2) + ' m/s';
paramVcmForce.textContent = state.vcmForce.toFixed(0) + ' N';
paramVcmCurrent.textContent = state.vcmCurrent.toFixed(1) + ' A';
paramVibration.textContent = state.vibration.toFixed(1) + ' mm';
// 参数颜色动态
paramVibration.setAttribute('fill', state.vibration > 3 ? '#ff5252' : state.vibration > 1 ? '#ffab00' : '#00e676');
// 阶段文本
if (state.mode === 'auto') {
const cfg = PHASES[state.phase] || PHASES[0];
phaseText.textContent = cfg.name;
} else {
phaseText.textContent = 'MANUAL';
}
// 手动模式参数显示
if (state.mode === 'manual') {
manualSpeedVal.textContent = state.shuttleSpeed.toFixed(1);
manualForkVal.textContent = (state.forkExtension * 100).toFixed(0) + '%';
}
}
// ============================
// 主循环
// ============================
let lastTime = 0;
function animate(timestamp) {
if (!lastTime) lastTime = timestamp;
const rawDt = (timestamp - lastTime) / 1000;
lastTime = timestamp;
const dt = Math.min(rawDt, 0.05) * state.speedMul;
if (state.running) {
state.time += dt;
if (state.mode === 'auto') {
updateAutoPhase(dt);
} else {
updateManualPhase(dt);
}
}
render();
requestAnimationFrame(animate);
}
// ============================
// 控制绑定
// ============================
btnPlay.addEventListener('click', () => {
state.mode = 'auto';
state.running = true;
btnPlay.classList.add('active');
btnManual.classList.remove('active');
manualControls.style.display = 'none';
});
btnReset.addEventListener('click', () => {
state.phase = 0;
state.time = 0;
state.shuttleX = 80;
state.shuttleSpeed = 0;
state.vibration = 0;
state.dampingForce = 0;
state.forkExtension = 0;
state.forkSpeed = 0;
state.vcmForce = 0;
state.vcmCurrent = 0;
state.eddyIntensity = 0;
state.waveformHistory = [];
state.running = true;
});
btnManual.addEventListener('click', () => {
state.mode = 'manual';
state.running = true;
btnManual.classList.add('active');
btnPlay.classList.remove('active');
manualControls.style.display = 'flex';
// 重置到合理位置
state.shuttleX = 200;
state.phase = 3; // 视觉上显示为手动模式
});
speedMulSlider.addEventListener('input', (e) => {
state.speedMul = parseFloat(e.target.value);
speedMulVal.textContent = state.speedMul.toFixed(1) + 'x';
});
manualSpeedSlider.addEventListener('input', (e) => {
// 手动模式下直接设置目标速度
});
manualForkSlider.addEventListener('input', (e) => {
// 手动模式下直接设置目标叉行程
});
// ============================
// 初始化
// ============================
initEddyCircles();
requestAnimationFrame(animate);
</script>
</body>
</html>
这段代码实现了一个完整的 IFR 原理动画,以下是核心设计说明:
视觉叙事与 IFR 思想映射
场代实(核心 IFR):动画全程不展示"删除前的机械结构",而是直接呈现最终理想解——涡流阻尼器和音圈电机的工作状态。涡流效果用旋转的虚线椭圆环表示,在轨道侧面上动态生成,强度与车速成正比,直观呈现"振动速度越快,阻尼力越强"这一自适应性。
资源利用:永磁体利用穿梭车自身的运动速度作为"资源"——无需外部供能,运动本身即产生阻尼。动画中通过磁场线(从永磁体延伸到轨道侧面的虚线弧)和涡流环的同屏出现,暗示这种"自给自足"的工作机理。
视觉引导:
- 涡流阻尼:青色(#00e5ff)发光效果 + 阻尼力箭头 + 车体振动波形线,三者联动——涡流越强,振幅波形越小
- 音圈电机:橙色(#ff6d00)力箭头 + VCM线圈发光强度变化 + 实时电流波形面板
- 0.5mm间隙:在高速阶段自动高亮标注,强调非接触特性
交互性:
- AUTO PLAY:自动循环演示完整时序(高速→减速→伸叉→柔性制动→完成)
- MANUAL:切换手动模式,分别控制"车速度"和"叉行程"滑块,独立体验两个创新点
- 速度倍率:0.3x~2.0x 可调,便于慢放观察细节
右侧信息面板:涡流阻尼器截面详图(含间隙标注和旋转涡流)、洛伦兹力公式(F=BIL)、VCM电流波形实时显示,为原理理解提供多维度支撑。
积分规则:第一轮对话扣减6分,后续每轮扣4分
等待动画代码生成...
