独立渲染引擎就绪引擎就绪
<!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>
实现说明:
IFR 理想解聚焦:动画直接呈现最终理想状态——无任何外挂线缆,铜排内嵌于铝型材腔体,碳刷滑触取电。左下角与右下角的信息卡片分别点明 IFR 核心思想与"第三轨供电"类比原理。
视觉引导:
- 铜排使用铜色渐变高亮,电流流动以青色(cyan)虚线沿铜排方向持续动画,清晰标示供电/回线路径。
- 接触点发光:碳刷与铜排接触处使用脉冲发光圆 + 随机火花粒子,将不可见的电接触转化为强烈视觉信号。
- 绝缘层以斜线剖面填充(hatch pattern)区分于铜排,一目了然。
横截面 inset(右上角):展示 U 形铜排包覆绝缘层、碳刷与弹簧的端面关系,帮助理解三维结构。
交互性:
- 速度滑块:0~3x 调节滑块运动速度,电流流动动画速度同步变化。
- 拖拽模式:点击按钮切换后,可直接在 SVG 上拖拽滑块/屏幕手动控制位移,体验"手推 → 碳刷滑触 → 取电"的完整时序。
- 标注开关:可隐藏/显示所有技术标注。
自动播放:页面加载后滑块立即自动往返运动,无需任何手动触发;重新加载同样自动开始。
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
