分享图
动画工坊
引擎就绪
<!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 rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@600;700;800&family=IBM+Plex+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
  --bg:#060a12;--surface:#0b1221;--grid:#0f1a2f;
  --text:#c0cfe0;--dim:#4a6080;--copper:#d07028;--copper-hi:#f0a050;
  --alu:#7a8da5;--alu-hi:#a8b8cc;--insul:#185838;
  --cyan:#00d4ff;--cyan-g:rgba(0,212,255,.55);
  --accent:#ff2850;--screen:#3878e8;
}
html,body{height:100%;overflow:hidden}
body{
  background:var(--bg);color:var(--text);
  font-family:'IBM Plex Mono',monospace;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
}
.wrap{width:100%;max-width:1260px;padding:12px 16px;display:flex;flex-direction:column;align-items:center;gap:10px}
h1{
  font-family:'Syne',sans-serif;font-weight:800;font-size:clamp(22px,3.2vw,38px);
  letter-spacing:-.02em;color:#e8f0fa;
  text-shadow:0 0 30px rgba(0,212,255,.18);
}
.sub{font-size:clamp(11px,1.3vw,14px);color:var(--dim);margin-top:-4px;letter-spacing:.06em}
.svg-box{width:100%;aspect-ratio:1200/660;max-height:72vh}
.svg-box svg{width:100%;height:100%;display:block}
.ctrl{
  display:flex;align-items:center;gap:16px;flex-wrap:wrap;justify-content:center;
  font-size:13px;color:var(--dim);
}
.ctrl label{display:flex;align-items:center;gap:6px}
.ctrl input[type=range]{
  width:120px;accent-color:var(--cyan);cursor:pointer;
}
.ctrl .val{color:var(--cyan);min-width:36px;text-align:right;font-weight:500}
.ctrl button{
  background:rgba(0,212,255,.08);border:1px solid rgba(0,212,255,.25);
  color:var(--cyan);padding:4px 14px;border-radius:4px;cursor:pointer;
  font-family:inherit;font-size:12px;transition:all .2s;
}
.ctrl button:hover{background:rgba(0,212,255,.18)}
.ctrl button.active{background:rgba(0,212,255,.22);border-color:var(--cyan)}

/* 电流流动动画 */
.flow-fwd{animation:fwd .9s linear infinite}
.flow-rev{animation:rev .9s linear infinite}
@keyframes fwd{to{stroke-dashoffset:-18}}
@keyframes rev{to{stroke-dashoffset:18}}
.pulse{animation:glow-pulse 1.6s ease-in-out infinite alternate}
@keyframes glow-pulse{0%{opacity:.55}100%{opacity:1}}

/* 标注淡入 */
.label-fade{opacity:0;animation:labIn 1.2s ease forwards}
.label-fade:nth-child(2){animation-delay:.3s}
.label-fade:nth-child(3){animation-delay:.6s}
.label-fade:nth-child(4){animation-delay:.9s}
@keyframes labIn{to{opacity:1}}

@media(prefers-reduced-motion:reduce){
  .flow-fwd,.flow-rev,.pulse,.label-fade{animation:none!important;opacity:1}
}
</style>
</head>
<body>
<div class="wrap">
  <h1>内嵌铜排滑轨 · 导电与导向一体化</h1>
  <p class="sub">IFR 理想解:消除外挂线缆,机械导向与电气传输同体实现</p>
  <div class="svg-box">
    <svg id="svg" viewBox="0 0 1200 660" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- 金属渐变 -->
        <linearGradient id="gAlu" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#a0b0c4"/><stop offset="40%" stop-color="#7a8da5"/>
          <stop offset="100%" stop-color="#5a6e84"/>
        </linearGradient>
        <linearGradient id="gCopper" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stop-color="#b06020"/><stop offset="30%" stop-color="#e08838"/>
          <stop offset="70%" stop-color="#d07028"/><stop offset="100%" stop-color="#a05818"/>
        </linearGradient>
        <linearGradient id="gScreen" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#1a3a6a"/><stop offset="100%" stop-color="#0e2240"/>
        </linearGradient>
        <!-- 发光滤镜 -->
        <filter id="fGlow" x="-60%" y="-60%" width="220%" height="220%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="6" result="b"/>
          <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="fGlowSm" x="-40%" y="-40%" width="180%" height="180%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="b"/>
          <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="fSpark" x="-100%" y="-100%" width="300%" height="300%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="2"/>
        </filter>
        <!-- 网格 -->
        <pattern id="grid" width="32" height="32" patternUnits="userSpaceOnUse">
          <path d="M32 0V32H0" fill="none" stroke="#0d1628" stroke-width=".5"/>
        </pattern>
        <!-- 绝缘剖面线 -->
        <pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
          <line x1="0" y1="0" x2="0" y2="6" stroke="#1a6840" stroke-width="1.2"/>
        </pattern>
      </defs>

      <!-- 背景网格 -->
      <rect width="1200" height="660" fill="url(#grid)"/>
      <rect width="1200" height="660" fill="url(#grid)" opacity=".4"/>

      <!-- ====== 型材滑轨(固定)====== -->
      <g id="profile">
        <!-- 外壳 -->
        <rect x="90" y="260" width="960" height="16" rx="2" fill="url(#gAlu)" opacity=".92"/>
        <rect x="90" y="384" width="960" height="16" rx="2" fill="url(#gAlu)" opacity=".92"/>
        <!-- 左右端盖 -->
        <rect x="90" y="260" width="18" height="140" rx="2" fill="url(#gAlu)" opacity=".85"/>
        <rect x="1032" y="260" width="18" height="140" rx="2" fill="url(#gAlu)" opacity=".85"/>
        <!-- 腔体背景 -->
        <rect x="108" y="276" width="924" height="108" rx="1" fill="#080e1a"/>
        <!-- 绝缘层(上) -->
        <rect x="108" y="276" width="924" height="6" fill="url(#hatch)" opacity=".7"/>
        <rect x="108" y="276" width="924" height="6" fill="#1a6840" opacity=".25"/>
        <!-- 铜排(上) -->
        <rect id="topBusbar" x="108" y="282" width="924" height="12" rx="1" fill="url(#gCopper)"/>
        <!-- 绝缘层(下) -->
        <rect x="108" y="378" width="924" height="6" fill="url(#hatch)" opacity=".7"/>
        <rect x="108" y="378" width="924" height="6" fill="#1a6840" opacity=".25"/>
        <!-- 铜排(下) -->
        <rect id="botBusbar" x="108" y="370" width="924" height="12" rx="1" fill="url(#gCopper)"/>
        <!-- 端面密封标注线 -->
        <line x1="108" y1="276" x2="108" y2="384" stroke="#1a6840" stroke-width="1.5" stroke-dasharray="3 3" opacity=".5"/>
        <line x1="1032" y1="276" x2="1032" y2="384" stroke="#1a6840" stroke-width="1.5" stroke-dasharray="3 3" opacity=".5"/>
        <!-- 电源符号(左端) -->
        <g transform="translate(62,285)">
          <rect x="-18" y="-8" width="36" height="16" rx="3" fill="none" stroke="var(--accent)" stroke-width="1.2"/>
          <text x="0" y="4" text-anchor="middle" fill="var(--accent)" font-size="11" font-weight="700">DC</text>
          <line x1="18" y1="0" x2="28" y2="0" stroke="var(--accent)" stroke-width="1.5"/>
          <text x="0" y="22" text-anchor="middle" fill="var(--dim)" font-size="9">24V</text>
        </g>
        <g transform="translate(62,373)">
          <line x1="-10" y1="0" x2="10" y2="0" stroke="var(--dim)" stroke-width="1.5"/>
          <line x1="-6" y1="5" x2="6" y2="5" stroke="var(--dim)" stroke-width="1"/>
          <line x1="10" y1="0" x2="28" y2="0" stroke="var(--dim)" stroke-width="1.5"/>
          <text x="0" y="18" text-anchor="middle" fill="var(--dim)" font-size="9">GND</text>
        </g>
      </g>

      <!-- ====== 铜排电流流动(固定, CSS动画) ====== -->
      <line id="flowTop" x1="108" y1="288" x2="1032" y2="288"
        stroke="var(--cyan)" stroke-width="3" stroke-dasharray="6 12"
        fill="none" class="flow-fwd" opacity=".7" filter="url(#fGlowSm)"/>
      <line id="flowBot" x1="108" y1="376" x2="1032" y2="376"
        stroke="var(--cyan)" stroke-width="3" stroke-dasharray="6 12"
        fill="none" class="flow-rev" opacity=".7" filter="url(#fGlowSm)"/>

      <!-- ====== 接触点发光(跟随滑块) ====== -->
      <circle id="glowTop" cx="275" cy="288" r="10" fill="var(--cyan)" opacity=".65" filter="url(#fGlow)" class="pulse"/>
      <circle id="glowBot" cx="275" cy="376" r="10" fill="var(--cyan)" opacity=".65" filter="url(#fGlow)" class="pulse"/>

      <!-- ====== 滑块组(整体平移) ====== -->
      <g id="sliderG" transform="translate(200,0)">
        <!-- 碳刷(上) -->
        <rect x="48" y="294" width="54" height="10" rx="2" fill="#2a2a2e" stroke="#444" stroke-width=".8"/>
        <rect x="52" y="294" width="46" height="3" rx="1" fill="#555" opacity=".5"/>
        <!-- 恒力弹簧(上) -->
        <path d="M56,304 l4,4 -8,0 8,0 -8,0 8,0 -4,4" stroke="#6888a8" stroke-width="1.8" fill="none" stroke-linecap="round"/>
        <!-- 滑块主体 -->
        <rect x="0" y="312" width="150" height="48" rx="4" fill="#1a2030" stroke="#2a3a55" stroke-width="1.2"/>
        <rect x="4" y="316" width="142" height="40" rx="3" fill="#101828" stroke="#1e2e48" stroke-width=".6"/>
        <!-- 内部走线示意 -->
        <line x1="75" y1="304" x2="75" y2="316" stroke="var(--cyan)" stroke-width="1.2" opacity=".5"/>
        <line x1="75" y1="356" x2="75" y2="370" stroke="var(--cyan)" stroke-width="1.2" opacity=".5"/>
        <path d="M75,316 L75,326 L110,326 L110,316" stroke="var(--cyan)" stroke-width=".8" fill="none" opacity=".35"/>
        <!-- 恒力弹簧(下) -->
        <path d="M56,360 l4,4 -8,0 8,0 -8,0 8,0 -4,4" stroke="#6888a8" stroke-width="1.8" fill="none" stroke-linecap="round" transform="rotate(180,75,366)"/>
        <!-- 碳刷(下) -->
        <rect x="48" y="368" width="54" height="10" rx="2" fill="#2a2a2e" stroke="#444" stroke-width=".8"/>
        <rect x="52" y="375" width="46" height="3" rx="1" fill="#555" opacity=".5"/>

        <!-- 自锁机构示意 -->
        <g opacity=".6">
          <rect x="128" y="318" width="16" height="8" rx="1.5" fill="#3a2828" stroke="#804040" stroke-width=".6"/>
          <path d="M131,322 l5,-3 l5,3" stroke="#c06050" stroke-width="1" fill="none"/>
        </g>

        <!-- 连接线(从滑块顶部到触摸屏) -->
        <path id="cable" d="M75,294 L75,260 Q75,250 75,245 L75,225"
          stroke="#3a5a80" stroke-width="3" fill="none" stroke-linecap="round"/>
        <path d="M75,294 L75,260 Q75,250 75,245 L75,225"
          stroke="var(--cyan)" stroke-width="1.5" fill="none" stroke-dasharray="4 6"
          class="flow-fwd" opacity=".55"/>

        <!-- 航空插座 -->
        <g transform="translate(75,240)">
          <circle cx="0" cy="0" r="8" fill="#1a2030" stroke="#4a6a90" stroke-width="1.2"/>
          <circle cx="0" cy="0" r="3.5" fill="#2a3a55"/>
          <circle cx="0" cy="0" r="1.5" fill="var(--cyan)" opacity=".6"/>
        </g>

        <!-- 触摸屏 -->
        <g id="screenG">
          <rect x="5" y="118" width="140" height="105" rx="6" fill="#0a0e18" stroke="#2a4a70" stroke-width="1.5"/>
          <rect x="10" y="123" width="130" height="90" rx="4" fill="url(#gScreen)"/>
          <!-- 屏幕内容 -->
          <g id="screenContent" opacity=".9">
            <rect x="18" y="132" width="50" height="6" rx="2" fill="#2a5a9a" opacity=".7"/>
            <rect x="18" y="143" width="70" height="4" rx="1.5" fill="#1a3a6a" opacity=".6"/>
            <rect x="18" y="152" width="55" height="4" rx="1.5" fill="#1a3a6a" opacity=".5"/>
            <rect x="18" y="166" width="36" height="18" rx="3" fill="#1a4a88" stroke="#2a6aaa" stroke-width=".6"/>
            <text x="36" y="179" text-anchor="middle" fill="#5a9add" font-size="8" font-family="IBM Plex Mono">RUN</text>
            <rect x="60" y="166" width="36" height="18" rx="3" fill="#1a4a88" stroke="#2a6aaa" stroke-width=".6"/>
            <text x="78" y="179" text-anchor="middle" fill="#5a9add" font-size="8" font-family="IBM Plex Mono">SET</text>
            <rect x="102" y="166" width="30" height="18" rx="3" fill="#1a4a88" stroke="#2a6aaa" stroke-width=".6"/>
            <text x="117" y="179" text-anchor="middle" fill="#5a9add" font-size="7" font-family="IBM Plex Mono">MSG</text>
            <!-- 状态条 -->
            <rect x="18" y="192" width="114" height="12" rx="2" fill="#0e1e38"/>
            <rect x="20" y="194" width="68" height="8" rx="1.5" fill="#1a5aaa" opacity=".7"/>
          </g>
          <!-- 屏幕发光边框 -->
          <rect x="10" y="123" width="130" height="90" rx="4" fill="none" stroke="var(--cyan)" stroke-width=".8" opacity=".3" class="pulse"/>
        </g>
        <!-- 推拉手柄示意 -->
        <rect x="55" y="108" width="40" height="10" rx="3" fill="#2a3a55" stroke="#3a5a80" stroke-width=".8"/>
        <line x1="68" y1="111" x2="82" y2="111" stroke="#4a6a90" stroke-width="1"/>
        <line x1="68" y1="114" x2="82" y2="114" stroke="#4a6a90" stroke-width="1"/>
      </g>

      <!-- ====== 火花粒子容器 ====== -->
      <g id="sparks"></g>

      <!-- ====== 横截面 inset ====== -->
      <g transform="translate(930,30)">
        <rect x="0" y="0" width="245" height="195" rx="6" fill="#080e1a" stroke="#1a2a48" stroke-width="1"/>
        <text x="122" y="18" text-anchor="middle" fill="var(--dim)" font-size="10" font-weight="500">横截面示意</text>
        <!-- 外壳截面 -->
        <rect x="30" y="28" width="185" height="150" rx="4" fill="none" stroke="var(--alu)" stroke-width="3"/>
        <!-- 内腔 -->
        <rect x="36" y="34" width="173" height="138" rx="2" fill="#060a14"/>
        <!-- 上铜排(U形) -->
        <path d="M42,40 h160 v20 h-20 v-8 h-120 v8 h-20 z" fill="url(#gCopper)" stroke="#a05818" stroke-width=".8"/>
        <rect x="42" y="34" width="160" height="6" fill="url(#hatch)" opacity=".6"/>
        <!-- 下铜排(U形倒置) -->
        <path d="M42,150 h160 v20 h-20 v-8 h-120 v8 h-20 z" fill="url(#gCopper)" stroke="#a05818" stroke-width=".8" transform="rotate(180,122,160)"/>
        <rect x="42" y="164" width="160" height="6" fill="url(#hatch)" opacity=".6"/>
        <!-- 滑块截面 -->
        <rect x="60" y="72" width="124" height="50" rx="3" fill="#1a2030" stroke="#2a3a55" stroke-width="1"/>
        <!-- 上碳刷截面 -->
        <rect x="90" y="60" width="38" height="12" rx="2" fill="#2a2a2e" stroke="#444" stroke-width=".6"/>
        <line x1="94" y1="62" x2="124" y2="62" stroke="#555" stroke-width=".8"/>
        <!-- 上弹簧 -->
        <path d="M98,72 l3,4 -6,0 6,0 -6,0 6,0 -3,3" stroke="#6888a8" stroke-width="1.2" fill="none"/>
        <!-- 下碳刷截面 -->
        <rect x="90" y="122" width="38" height="12" rx="2" fill="#2a2a2e" stroke="#444" stroke-width=".6"/>
        <line x1="94" y1="132" x2="124" y2="132" stroke="#555" stroke-width=".8"/>
        <!-- 下弹簧 -->
        <path d="M98,122 l3,-4 -6,0 6,0 -6,0 6,0 -3,-3" stroke="#6888a8" stroke-width="1.2" fill="none"/>
        <!-- 接触点发光 -->
        <circle cx="109" cy="60" r="4" fill="var(--cyan)" opacity=".45" filter="url(#fGlowSm)"/>
        <circle cx="109" cy="134" r="4" fill="var(--cyan)" opacity=".45" filter="url(#fGlowSm)"/>
        <!-- 标注 -->
        <text x="228" y="52" fill="var(--copper-hi)" font-size="8" font-weight="500">铜排</text>
        <text x="228" y="108" fill="var(--alu-hi)" font-size="8" font-weight="500">滑块</text>
        <text x="228" y="150" fill="var(--copper-hi)" font-size="8" font-weight="500">铜排</text>
      </g>

      <!-- ====== 标注 ====== -->
      <g id="labels" font-family="'IBM Plex Mono',monospace" font-size="11" font-weight="400">
        <!-- 铝型材 -->
        <g class="label-fade">
          <line x1="540" y1="410" x2="540" y2="432" stroke="var(--dim)" stroke-width=".8"/>
          <text x="540" y="446" text-anchor="middle" fill="var(--alu-hi)">铝型材滑轨(中空腔体)</text>
        </g>
        <!-- 上铜排 -->
        <g class="label-fade">
          <line x1="680" y1="288" x2="760" y2="254" stroke="var(--dim)" stroke-width=".8" stroke-dasharray="3 2"/>
          <text x="762" y="250" fill="var(--copper-hi)" font-weight="500">导电铜排</text>
          <text x="762" y="264" fill="var(--dim)" font-size="9">≥ 2.5mm²</text>
        </g>
        <!-- 下铜排 -->
        <g class="label-fade">
          <line x1="680" y1="376" x2="760" y2="400" stroke="var(--dim)" stroke-width=".8" stroke-dasharray="3 2"/>
          <text x="762" y="404" fill="var(--copper-hi)" font-weight="500">信号/地线铜排</text>
        </g>
        <!-- 绝缘层 -->
        <g class="label-fade">
          <line x1="860" y1="279" x2="900" y2="260" stroke="var(--dim)" stroke-width=".8" stroke-dasharray="3 2"/>
          <text x="902" y="258" fill="#3aaa6a" font-size="10">绝缘包覆</text>
        </g>
      </g>

      <!-- 动态标注(跟随滑块) -->
      <g id="dynLabels" font-family="'IBM Plex Mono',monospace" font-size="10">
        <g id="lblBrush">
          <line x1="0" y1="299" x2="0" y2="480" stroke="var(--dim)" stroke-width=".6" stroke-dasharray="2 2"/>
          <text x="0" y="494" text-anchor="middle" fill="#8a8a9a">碳刷</text>
          <text x="0" y="508" text-anchor="middle" fill="var(--dim)" font-size="9">接触压力 1.5~2.0N</text>
        </g>
        <g id="lblSpring">
          <line x1="0" y1="360" x2="40" y2="480" stroke="var(--dim)" stroke-width=".6" stroke-dasharray="2 2"/>
          <text x="42" y="486" fill="#6a8aaa" font-size="9">恒力弹簧</text>
        </g>
        <g id="lblScreen">
          <text x="0" y="106" text-anchor="middle" fill="#5a8abb" font-size="10">工业触摸屏</text>
        </g>
      </g>

      <!-- 方向箭头 -->
      <g id="dirArrow" opacity=".5">
        <line x1="0" y1="440" x2="60" y2="440" stroke="var(--cyan)" stroke-width="1.5" marker-end="url(#arrHead)"/>
      </g>
      <defs>
        <marker id="arrHead" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto">
          <path d="M0,0 L8,3 L0,6" fill="var(--cyan)"/>
        </marker>
      </defs>

      <!-- IFR 理想解标注 -->
      <g transform="translate(50,580)">
        <rect x="0" y="0" width="320" height="56" rx="4" fill="rgba(0,212,255,.04)" stroke="rgba(0,212,255,.15)" stroke-width="1"/>
        <text x="14" y="18" fill="var(--cyan)" font-size="10" font-weight="600" font-family="Syne,sans-serif">IFR 最终理想解</text>
        <text x="14" y="34" fill="var(--dim)" font-size="9.5">消除外挂线缆 → 铜排内嵌型材 → 导电导向同体</text>
        <text x="14" y="48" fill="var(--dim)" font-size="9.5">零弯折疲劳 · 零断线风险 · 极致紧凑</text>
      </g>

      <!-- 原理引用 -->
      <g transform="translate(830,580)">
        <rect x="0" y="0" width="320" height="56" rx="4" fill="rgba(208,112,40,.04)" stroke="rgba(208,112,40,.15)" stroke-width="1"/>
        <text x="14" y="18" fill="var(--copper-hi)" font-size="10" font-weight="600" font-family="Syne,sans-serif">第三轨供电原理</text>
        <text x="14" y="34" fill="var(--dim)" font-size="9.5">地铁受电靴 → 碳刷滑触铜排</text>
        <text x="14" y="48" fill="var(--dim)" font-size="9.5">机械位移同时完成电气传输</text>
      </g>

    </svg>
  </div>
  <div class="ctrl">
    <label>
      <span>速度</span>
      <input type="range" id="spdR" min="0" max="3" step="0.1" value="1">
      <span class="val" id="spdV">1.0x</span>
    </label>
    <button id="btnDrag" title="拖拽滑块手动控制">拖拽模式</button>
    <button id="btnLabel" class="active" title="显示/隐藏标注">标注</button>
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded',()=>{
  /* ====== 配置 ====== */
  const C={
    minX:150, maxX:820, baseSpd:.65,
    profileLeft:108, profileRight:1032,
    sliderW:150,
    brushOffsetX:75, // 碳刷中心相对滑块组原点
    topBusY:288, botBusY:376,
  };

  /* ====== 状态 ====== */
  let sx=200, dir=1, spd=1, dragging=false, dragOff=0, showLabels=true, dragMode=false;
  let sparkPool=[];

  /* ====== DOM ====== */
  const svg=document.getElementById('svg');
  const sliderG=document.getElementById('sliderG');
  const glowT=document.getElementById('glowTop');
  const glowB=document.getElementById('glowBot');
  const sparksG=document.getElementById('sparks');
  const lblBrush=document.getElementById('lblBrush');
  const lblSpring=document.getElementById('lblSpring');
  const lblScreen=document.getElementById('lblScreen');
  const dirArrow=document.getElementById('dirArrow');
  const spdR=document.getElementById('spdR');
  const spdV=document.getElementById('spdV');
  const btnDrag=document.getElementById('btnDrag');
  const btnLabel=document.getElementById('btnLabel');
  const labelsG=document.getElementById('labels');
  const dynLabelsG=document.getElementById('dynLabels');

  /* ====== 速度控制 ====== */
  spdR.addEventListener('input',()=>{
    spd=parseFloat(spdR.value);
    spdV.textContent=spd.toFixed(1)+'x';
  });

  /* ====== 拖拽模式 ====== */
  btnDrag.addEventListener('click',()=>{
    dragMode=!dragMode;
    btnDrag.classList.toggle('active',dragMode);
    btnDrag.textContent=dragMode?'自动播放':'拖拽模式';
  });

  /* ====== 标注开关 ====== */
  btnLabel.addEventListener('click',()=>{
    showLabels=!showLabels;
    btnLabel.classList.toggle('active',showLabels);
    labelsG.style.opacity=showLabels?1:0;
    dynLabelsG.style.opacity=showLabels?1:0;
  });

  /* ====== SVG坐标转换 ====== */
  function svgPt(e){
    const pt=svg.createSVGPoint();
    const src=e.touches?e.touches[0]:e;
    pt.x=src.clientX; pt.y=src.clientY;
    return pt.matrixTransform(svg.getScreenCTM().inverse());
  }

  /* ====== 拖拽交互 ====== */
  function onDown(e){
    if(!dragMode)return;
    const p=svgPt(e);
    // 检查是否点在滑块/屏幕区域
    const cx=sx+C.brushOffsetX;
    if(p.x>sx-20&&p.x<sx+C.sliderW+20&&p.y>100&&p.y<420){
      dragging=true;
      dragOff=p.x-sx;
      e.preventDefault();
    }
  }
  function onMove(e){
    if(!dragging)return;
    const p=svgPt(e);
    sx=Math.max(C.minX,Math.min(C.maxX,p.x-dragOff));
    e.preventDefault();
  }
  function onUp(){dragging=false;}

  svg.addEventListener('mousedown',onDown);
  svg.addEventListener('mousemove',onMove);
  svg.addEventListener('mouseup',onUp);
  svg.addEventListener('touchstart',onDown,{passive:false});
  svg.addEventListener('touchmove',onMove,{passive:false});
  svg.addEventListener('touchend',onUp);

  /* ====== 火花系统 ====== */
  function spawnSpark(cx,cy){
    const angle=Math.random()*Math.PI*2;
    const r=Math.random()*8+3;
    const el=document.createElementNS('http://www.w3.org/2000/svg','circle');
    el.setAttribute('cx',cx+Math.cos(angle)*r*.3);
    el.setAttribute('cy',cy+Math.sin(angle)*r*.3);
    el.setAttribute('r',Math.random()*1.8+.6);
    el.setAttribute('fill','#00d4ff');
    el.setAttribute('opacity','0.9');
    el.setAttribute('filter','url(#fSpark)');
    sparksG.appendChild(el);
    sparkPool.push({el,cx,cy,vx:Math.cos(angle)*1.5,vy:Math.sin(angle)*1.5,life:1});
  }

  function updateSparks(){
    for(let i=sparkPool.length-1;i>=0;i--){
      const s=sparkPool[i];
      s.life-=.04;
      if(s.life<=0){
        s.el.remove();
        sparkPool.splice(i,1);
        continue;
      }
      const nx=parseFloat(s.el.getAttribute('cx'))+s.vx;
      const ny=parseFloat(s.el.getAttribute('cy'))+s.vy;
      s.el.setAttribute('cx',nx);
      s.el.setAttribute('cy',ny);
      s.el.setAttribute('opacity',s.life*.8);
      s.el.setAttribute('r',Math.max(.2,s.life*1.5));
    }
  }

  /* ====== 主动画循环 ====== */
  let lastSpark=0;

  function animate(ts){
    // 滑块移动
    if(!dragging){
      sx+=dir*C.baseSpd*spd;
      if(sx>=C.maxX){dir=-1;sx=C.maxX;}
      if(sx<=C.minX){dir=1;sx=C.minX;}
    }

    // 更新滑块组
    sliderG.setAttribute('transform','translate('+sx+',0)');

    // 接触点发光跟随
    const cx=sx+C.brushOffsetX;
    glowT.setAttribute('cx',cx);
    glowB.setAttribute('cx',cx);

    // 动态标注跟随
    lblBrush.setAttribute('transform','translate('+cx+',0)');
    lblSpring.setAttribute('transform','translate('+(sx+60)+',0)');
    lblScreen.setAttribute('transform','translate('+cx+',0)');

    // 方向箭头
    const arrowX=cx+(dir>0?30:-90);
    dirArrow.setAttribute('transform','translate('+arrowX+',0)');
    dirArrow.querySelector('line').setAttribute('x2',dir>0?50:-50);

    // 火花
    if(ts-lastSpark>120&&spd>0){
      spawnSpark(cx,C.topBusY);
      spawnSpark(cx,C.botBusY);
      lastSpark=ts;
    }
    updateSparks();

    // 电流流动速度与滑块速度联动
    const flowDur=Math.max(.3,1.2-spd*.3);
    document.getElementById('flowTop').style.animationDuration=flowDur+'s';
    document.getElementById('flowBot').style.animationDuration=flowDur+'s';

    requestAnimationFrame(animate);
  }

  requestAnimationFrame(animate);
});
</script>
</body>
</html>

实现说明:

  1. IFR 理想解聚焦:动画直接呈现最终理想状态——无任何外挂线缆,铜排内嵌于铝型材腔体,碳刷滑触取电。左下角与右下角的信息卡片分别点明 IFR 核心思想与"第三轨供电"类比原理。

  2. 视觉引导

    • 铜排使用铜色渐变高亮,电流流动以青色(cyan)虚线沿铜排方向持续动画,清晰标示供电/回线路径。
    • 接触点发光:碳刷与铜排接触处使用脉冲发光圆 + 随机火花粒子,将不可见的电接触转化为强烈视觉信号。
    • 绝缘层以斜线剖面填充(hatch pattern)区分于铜排,一目了然。
  3. 横截面 inset(右上角):展示 U 形铜排包覆绝缘层、碳刷与弹簧的端面关系,帮助理解三维结构。

  4. 交互性

    • 速度滑块:0~3x 调节滑块运动速度,电流流动动画速度同步变化。
    • 拖拽模式:点击按钮切换后,可直接在 SVG 上拖拽滑块/屏幕手动控制位移,体验"手推 → 碳刷滑触 → 取电"的完整时序。
    • 标注开关:可隐藏/显示所有技术标注。
  5. 自动播放:页面加载后滑块立即自动往返运动,无需任何手动触发;重新加载同样自动开始。

积分规则:第一轮对话扣减8分,后续每轮扣6分