这个方案非常精妙——利用磁流变液的"固-液相变"为刚性孔壁增加柔性自对准过渡层,完全契合 TRIZ 的最终理想解(IFR):问题自身消失,资源自我服务。下面是完整的交互式原理动画:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>静电转移 + 磁流变液辅助定位 — 原理动画</title>
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=IBM+Plex+Mono:wght@300;400;500;600&display=swap" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<style>
:root {
--bg: #050910;
--surface: #0b1120;
--card: #0f1729;
--border: rgba(0,229,255,0.1);
--text: #c4d3e4;
--text-dim: #556677;
--accent: #00e5ff;
--amber: #ffa726;
--amber-dim: rgba(255,167,38,0.15);
--copper: #cd8032;
--mr-liquid: rgba(0,200,180,0.22);
--mr-solid: #00c8b4;
--funnel-glow: #00ffe0;
--magnetic: #9c6cff;
--success: #00e676;
}
*{margin:0;padding:0;box-sizing:border-box;}
body{
background:var(--bg);
color:var(--text);
font-family:'IBM Plex Mono',monospace;
min-height:100vh;
display:flex;
flex-direction:column;
align-items:center;
overflow-x:hidden;
}
/* 背景网格 */
body::before{
content:'';position:fixed;inset:0;
background-image:
linear-gradient(rgba(0,229,255,0.03) 1px,transparent 1px),
linear-gradient(90deg,rgba(0,229,255,0.03) 1px,transparent 1px);
background-size:60px 60px;
pointer-events:none;z-index:0;
}
body::after{
content:'';position:fixed;inset:0;
background:radial-gradient(ellipse at 50% 30%,rgba(0,229,255,0.04) 0%,transparent 60%);
pointer-events:none;z-index:0;
}
.container{
position:relative;z-index:1;
width:100%;max-width:1100px;
padding:28px 20px 40px;
display:flex;flex-direction:column;align-items:center;gap:20px;
}
/* 标题区 */
.header{text-align:center;margin-bottom:4px;}
.header h1{
font-family:'Syne',sans-serif;
font-weight:800;font-size:clamp(22px,3.2vw,36px);
letter-spacing:-0.5px;
background:linear-gradient(135deg,#e0eaf4 0%,var(--accent) 60%,var(--funnel-glow) 100%);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;
background-clip:text;
}
.header .sub{
font-size:13px;color:var(--text-dim);margin-top:6px;letter-spacing:0.5px;
}
.header .ifrtag{
display:inline-block;margin-top:8px;
padding:3px 12px;border-radius:20px;
background:rgba(0,229,255,0.08);border:1px solid rgba(0,229,255,0.2);
font-size:11px;color:var(--accent);letter-spacing:1px;
}
/* 主动画区 */
.anim-wrap{
width:100%;
background:var(--surface);
border:1px solid var(--border);
border-radius:16px;
overflow:hidden;
position:relative;
}
.anim-wrap svg{display:block;width:100%;height:auto;}
/* 控制面板 */
.controls{
width:100%;
display:flex;flex-wrap:wrap;align-items:center;gap:12px;
padding:16px 20px;
background:var(--card);
border:1px solid var(--border);
border-radius:12px;
}
.ctrl-group{display:flex;align-items:center;gap:8px;}
.ctrl-group.sep{margin-left:auto;}
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:6px;
padding:8px 16px;border-radius:8px;border:1px solid var(--border);
background:rgba(0,229,255,0.06);color:var(--accent);
font-family:inherit;font-size:12px;cursor:pointer;
transition:all .2s;
}
.btn:hover{background:rgba(0,229,255,0.14);border-color:rgba(0,229,255,0.3);}
.btn:active{transform:scale(0.96);}
.btn.primary{background:rgba(0,229,255,0.15);border-color:rgba(0,229,255,0.35);}
.btn i{font-size:13px;}
/* 进度条 */
.timeline-wrap{
flex:1;min-width:200px;
display:flex;align-items:center;gap:10px;
}
.timeline-wrap label{font-size:11px;color:var(--text-dim);white-space:nowrap;}
input[type=range]{
-webkit-appearance:none;appearance:none;
flex:1;height:6px;border-radius:3px;
background:rgba(0,229,255,0.1);outline:none;cursor:pointer;
}
input[type=range]::-webkit-slider-thumb{
-webkit-appearance:none;width:16px;height:16px;border-radius:50%;
background:var(--accent);border:2px solid var(--bg);
box-shadow:0 0 8px rgba(0,229,255,0.4);
}
/* 速度 */
.speed-btns{display:flex;gap:4px;}
.speed-btns .btn{padding:6px 10px;font-size:11px;min-width:36px;justify-content:center;}
.speed-btns .btn.active{background:rgba(0,229,255,0.2);border-color:var(--accent);}
/* 阶段指示器 */
.phase-bar{
width:100%;display:flex;gap:4px;
}
.phase-step{
flex:1;padding:10px 8px;border-radius:8px;
background:var(--card);border:1px solid var(--border);
text-align:center;transition:all .4s;
position:relative;overflow:hidden;
}
.phase-step::before{
content:'';position:absolute;inset:0;
background:linear-gradient(135deg,rgba(0,229,255,0.08),transparent);
opacity:0;transition:opacity .4s;
}
.phase-step.active::before{opacity:1;}
.phase-step.active{border-color:rgba(0,229,255,0.35);}
.phase-step.done{border-color:rgba(0,230,118,0.25);}
.phase-step .num{
font-size:10px;color:var(--text-dim);margin-bottom:3px;
font-weight:600;letter-spacing:1px;position:relative;
}
.phase-step.active .num{color:var(--accent);}
.phase-step.done .num{color:var(--success);}
.phase-step .label{
font-size:11px;color:var(--text-dim);position:relative;
font-weight:500;
}
.phase-step.active .label{color:#e0eaf4;}
.phase-step.done .label{color:rgba(0,230,118,0.7);}
/* 参数面板 */
.param-panel{
width:100%;
display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:10px;
}
.param-card{
padding:12px 16px;border-radius:10px;
background:var(--card);border:1px solid var(--border);
transition:all .5s;opacity:0.4;
}
.param-card.visible{opacity:1;border-color:rgba(0,229,255,0.2);}
.param-card .p-label{font-size:10px;color:var(--text-dim);letter-spacing:0.8px;margin-bottom:4px;text-transform:uppercase;}
.param-card .p-value{font-size:15px;font-weight:600;color:#e0eaf4;}
.param-card .p-value span{color:var(--accent);font-weight:700;}
.param-card .p-note{font-size:10px;color:var(--text-dim);margin-top:4px;line-height:1.5;}
@media(max-width:640px){
.container{padding:16px 10px 30px;}
.controls{flex-direction:column;align-items:stretch;}
.ctrl-group.sep{margin-left:0;}
.phase-bar{flex-wrap:wrap;}
.phase-step{min-width:calc(33% - 4px);}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>静电转移 + 磁流变液辅助定位</h1>
<p class="sub">细长铜柱(长径比 11:1)无卡死插入原理演示</p>
<span class="ifrtag">IFR:孔壁自身成为柔性导向 — 问题自行消失</span>
</div>
<div class="anim-wrap">
<svg id="scene" viewBox="0 0 800 920" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 金属渐变 -->
<linearGradient id="gMetal" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#4a5060"/>
<stop offset="50%" stop-color="#363c4a"/>
<stop offset="100%" stop-color="#2a2f3a"/>
</linearGradient>
<!-- 铜渐变 -->
<linearGradient id="gCopper" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#b06820"/>
<stop offset="30%" stop-color="#daa050"/>
<stop offset="70%" stop-color="#e8b868"/>
<stop offset="100%" stop-color="#b07028"/>
</linearGradient>
<!-- 玻璃渐变 -->
<linearGradient id="gGlass" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="rgba(160,200,240,0.1)"/>
<stop offset="100%" stop-color="rgba(120,170,220,0.06)"/>
</linearGradient>
<!-- 磁场线渐变 -->
<linearGradient id="gMag" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="rgba(156,108,255,0.6)"/>
<stop offset="100%" stop-color="rgba(156,108,255,0)"/>
</linearGradient>
<!-- 发光滤镜 -->
<filter id="fGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="fGlowBig" x="-80%" y="-80%" width="260%" height="260%">
<feGaussianBlur stdDeviation="14" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="fGlowSm" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- MR流体纹理 -->
<pattern id="mrPattern" width="8" height="8" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1" fill="rgba(0,210,190,0.3)"/>
</pattern>
</defs>
<!-- 背景装饰 -->
<rect x="0" y="0" width="800" height="920" fill="none"/>
<!-- ====== 磁场线组(Phase 3 可见) ====== -->
<g id="magLines" opacity="0">
<path d="M230,480 Q260,440 270,400" stroke="url(#gMag)" stroke-width="2" fill="none" stroke-dasharray="4,4"/>
<path d="M230,520 Q240,480 250,440" stroke="url(#gMag)" stroke-width="2" fill="none" stroke-dasharray="4,4"/>
<path d="M570,480 Q540,440 530,400" stroke="url(#gMag)" stroke-width="2" fill="none" stroke-dasharray="4,4"/>
<path d="M570,520 Q560,480 550,440" stroke="url(#gMag)" stroke-width="2" fill="none" stroke-dasharray="4,4"/>
<!-- 磁极标记 -->
<text x="210" y="510" font-size="16" fill="rgba(156,108,255,0.7)" font-family="Syne,sans-serif" font-weight="700">N</text>
<text x="575" y="510" font-size="16" fill="rgba(156,108,255,0.7)" font-family="Syne,sans-serif" font-weight="700">S</text>
</g>
<!-- ====== 玻璃板 ====== -->
<g id="glassGroup">
<!-- 左半玻璃 -->
<rect x="220" y="460" width="174" height="300" rx="2" fill="url(#gGlass)" stroke="rgba(140,180,220,0.15)" stroke-width="1"/>
<!-- 右半玻璃 -->
<rect x="406" y="460" width="174" height="300" rx="2" fill="url(#gGlass)" stroke="rgba(140,180,220,0.15)" stroke-width="1"/>
<!-- 玻璃标签 -->
<text x="306" y="620" font-size="10" fill="rgba(140,180,220,0.35)" text-anchor="middle" font-family="IBM Plex Mono,monospace" transform="rotate(-90,306,620)">玻璃基板</text>
<text x="494" y="620" font-size="10" fill="rgba(140,180,220,0.35)" text-anchor="middle" font-family="IBM Plex Mono,monospace" transform="rotate(90,494,620)">玻璃基板</text>
</g>
<!-- ====== MR流体 — 液态(浅槽 + 孔内) ====== -->
<rect id="mrTrough" x="220" y="430" width="360" height="30" rx="3" fill="rgba(0,200,180,0.18)" stroke="rgba(0,210,190,0.1)" stroke-width="0.5"/>
<rect id="mrHole" x="394" y="460" width="12" height="300" fill="rgba(0,200,180,0.22)"/>
<!-- ====== MR流体 — 固态漏斗(Phase 3 出现) ====== -->
<g id="funnelGroup" opacity="0">
<!-- 漏斗主体 -->
<path id="funnelShape" d="M374,430 L426,430 L404,510 L396,510 Z" fill="rgba(0,210,190,0.35)" stroke="rgba(0,255,224,0.3)" stroke-width="1"/>
<!-- 漏斗发光轮廓 -->
<path d="M374,430 L426,430 L404,510 L396,510 Z" fill="none" stroke="rgba(0,255,224,0.5)" stroke-width="1.5" filter="url(#fGlowSm)"/>
<!-- 漏斗内导向线 -->
<line x1="380" y1="445" x2="397" y2="505" stroke="rgba(0,255,224,0.15)" stroke-width="0.5" stroke-dasharray="3,3"/>
<line x1="420" y1="445" x2="403" y2="505" stroke="rgba(0,255,224,0.15)" stroke-width="0.5" stroke-dasharray="3,3"/>
<!-- 漏斗高亮脉冲 -->
<path id="funnelPulse" d="M374,430 L426,430 L404,510 L396,510 Z" fill="none" stroke="rgba(0,255,224,0.8)" stroke-width="2" filter="url(#fGlow)" opacity="0"/>
</g>
<!-- ====== MR流体粒子组 ====== -->
<g id="mrParticles"></g>
<!-- ====== 铜柱 ====== -->
<g id="pillarGroup">
<rect id="copperPillar" x="395" y="238" width="10" height="110" rx="1.5" fill="url(#gCopper)"/>
<!-- 铜柱顶端与电极接触面 -->
<rect id="pillarTop" x="395" y="236" width="10" height="4" rx="1" fill="#daa050"/>
</g>
<!-- ====== 静电转移头 ====== -->
<g id="headGroup">
<!-- 主体 -->
<rect x="280" y="80" width="240" height="140" rx="6" fill="url(#gMetal)" stroke="rgba(255,255,255,0.06)" stroke-width="1"/>
<!-- 内部电路纹理 -->
<line x1="300" y1="100" x2="500" y2="100" stroke="rgba(255,255,255,0.04)" stroke-width="0.5"/>
<line x1="300" y1="120" x2="500" y2="120" stroke="rgba(255,255,255,0.04)" stroke-width="0.5"/>
<line x1="300" y1="140" x2="500" y2="140" stroke="rgba(255,255,255,0.04)" stroke-width="0.5"/>
<line x1="300" y1="160" x2="500" y2="160" stroke="rgba(255,255,255,0.04)" stroke-width="0.5"/>
<line x1="300" y1="180" x2="500" y2="180" stroke="rgba(255,255,255,0.04)" stroke-width="0.5"/>
<!-- 微电极凸起 -->
<path d="M388,220 L412,220 L406,238 L394,238 Z" fill="#4a5060" stroke="rgba(255,255,255,0.08)" stroke-width="0.5"/>
<!-- 转移头标签 -->
<text x="400" y="158" font-size="11" fill="rgba(255,255,255,0.25)" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-weight="500">静电转移头</text>
</g>
<!-- ====== 静电场发光 ====== -->
<g id="electroGlow" opacity="0">
<ellipse cx="400" cy="240" rx="28" ry="12" fill="rgba(255,167,38,0.3)" filter="url(#fGlow)"/>
<ellipse cx="400" cy="238" rx="14" ry="5" fill="rgba(255,200,80,0.5)" filter="url(#fGlowSm)"/>
<!-- 静电力线 -->
<line x1="394" y1="238" x2="395" y2="250" stroke="rgba(255,167,38,0.4)" stroke-width="0.8" stroke-dasharray="2,3"/>
<line x1="400" y1="238" x2="400" y2="252" stroke="rgba(255,167,38,0.5)" stroke-width="0.8" stroke-dasharray="2,3"/>
<line x1="406" y1="238" x2="405" y2="250" stroke="rgba(255,167,38,0.4)" stroke-width="0.8" stroke-dasharray="2,3"/>
</g>
<!-- ====== 阵列缩略图(右上角) ====== -->
<g id="arrayInset" transform="translate(610,60)">
<rect x="0" y="0" width="150" height="150" rx="8" fill="rgba(11,17,32,0.85)" stroke="rgba(0,229,255,0.15)" stroke-width="1"/>
<text x="75" y="18" font-size="8" fill="var(--text-dim)" text-anchor="middle" font-family="IBM Plex Mono,monospace">22500根并行阵列</text>
<!-- 小点阵列 -->
<g id="arrayDots"></g>
<!-- 高亮当前操作列 -->
<rect id="arrayHighlight" x="69" y="27" width="12" height="12" rx="2" fill="none" stroke="var(--amber)" stroke-width="1.2" opacity="0"/>
</g>
<!-- ====== 参数标注(动态显示) ====== -->
<g id="callouts">
<!-- DC 50V 标注 -->
<g id="calloutVoltage" opacity="0">
<line x1="420" y1="200" x2="480" y2="175" stroke="rgba(255,167,38,0.4)" stroke-width="0.8" stroke-dasharray="3,2"/>
<rect x="480" y="164" width="80" height="22" rx="4" fill="rgba(255,167,38,0.1)" stroke="rgba(255,167,38,0.3)" stroke-width="0.8"/>
<text x="520" y="179" font-size="10" fill="#ffa726" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-weight="600">DC 50V</text>
</g>
<!-- 0.05mm 间隙标注 -->
<g id="calloutGap" opacity="0">
<line x1="410" y1="428" x2="470" y2="415" stroke="rgba(0,229,255,0.4)" stroke-width="0.8" stroke-dasharray="3,2"/>
<rect x="470" y="404" width="96" height="22" rx="4" fill="rgba(0,229,255,0.08)" stroke="rgba(0,229,255,0.25)" stroke-width="0.8"/>
<text x="518" y="419" font-size="10" fill="var(--accent)" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-weight="600">间隙 0.05mm</text>
</g>
<!-- 50kPa 标注 -->
<g id="calloutYield" opacity="0">
<line x1="426" y1="470" x2="490" y2="455" stroke="rgba(0,255,224,0.4)" stroke-width="0.8" stroke-dasharray="3,2"/>
<rect x="490" y="444" width="110" height="22" rx="4" fill="rgba(0,255,224,0.08)" stroke="rgba(0,255,224,0.25)" stroke-width="0.8"/>
<text x="545" y="459" font-size="10" fill="var(--funnel-glow)" text-anchor="middle" font-family="IBM Plex Mono,monospace" font-weight="600">50kPa 屈服强度</text>
</g>
</g>
<!-- ====== 阶段标题(SVG内) ====== -->
<g id="phaseTitle" transform="translate(50,45)">
<text id="phaseTitleText" font-size="14" fill="rgba(0,229,255,0.6)" font-family="Syne,sans-serif" font-weight="700" letter-spacing="1"></text>
</g>
<!-- ====== 成功指示 ====== -->
<g id="successMark" opacity="0" transform="translate(400,790)">
<circle cx="0" cy="0" r="16" fill="rgba(0,230,118,0.12)" stroke="rgba(0,230,118,0.4)" stroke-width="1.5"/>
<path d="M-6,0 L-2,5 L7,-5" stroke="#00e676" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<!-- ====== 铜柱下落轨迹 ====== -->
<g id="trailGroup" opacity="0">
<line id="fallTrail" x1="400" y1="350" x2="400" y2="500" stroke="rgba(205,128,50,0.15)" stroke-width="10" stroke-linecap="round" filter="url(#fGlowSm)"/>
</g>
</svg>
</div>
<!-- 控制面板 -->
<div class="controls">
<div class="ctrl-group">
<button class="btn primary" id="btnPlay"><i class="fa-solid fa-play"></i> 播放</button>
<button class="btn" id="btnStep"><i class="fa-solid fa-forward-step"></i> 下一阶段</button>
<button class="btn" id="btnReset"><i class="fa-solid fa-rotate-left"></i> 重置</button>
</div>
<div class="timeline-wrap">
<label>进度</label>
<input type="range" id="timeline" min="0" max="1000" value="0"/>
</div>
<div class="ctrl-group sep">
<label style="font-size:11px;color:var(--text-dim)">速度</label>
<div class="speed-btns">
<button class="btn" data-speed="0.5">0.5x</button>
<button class="btn active" data-speed="1">1x</button>
<button class="btn" data-speed="2">2x</button>
</div>
</div>
</div>
<!-- 阶段指示器 -->
<div class="phase-bar">
<div class="phase-step" data-idx="0"><div class="num">01</div><div class="label">静电吸取</div></div>
<div class="phase-step" data-idx="1"><div class="num">02</div><div class="label">移至对位</div></div>
<div class="phase-step" data-idx="2"><div class="num">03</div><div class="label">磁场固化</div></div>
<div class="phase-step" data-idx="3"><div class="num">04</div><div class="label">释放下落</div></div>
<div class="phase-step" data-idx="4"><div class="num">05</div><div class="label">撤磁排液</div></div>
<div class="phase-step" data-idx="5"><div class="num">06</div><div class="label">精准就位</div></div>
</div>
<!-- 参数面板 -->
<div class="param-panel">
<div class="param-card" id="pcVoltage">
<div class="p-label">静电转移头电压</div>
<div class="p-value"><span>DC 50V</span></div>
<div class="p-note">微电极凸起 Φ0.09mm,尺寸略小于铜柱</div>
</div>
<div class="param-card" id="pcGap">
<div class="p-label">对合间隙</div>
<div class="p-value"><span>0.05mm</span></div>
<div class="p-note">转移头与玻璃板精确对合距离</div>
</div>
<div class="param-card" id="pcYield">
<div class="p-label">磁流变液剪切屈服强度</div>
<div class="p-value"><span>50kPa</span>(励磁后)</div>
<div class="p-note">纳米级颗粒,固态形成柔性锥度漏斗</div>
</div>
<div class="param-card" id="pcIFR">
<div class="p-label">IFR 核心原理</div>
<div class="p-value">孔壁<span>自我导向</span></div>
<div class="p-note">磁流变液相变 → 刚性孔变为柔性自对准孔,硬接触卡死矛盾自行消失</div>
</div>
</div>
</div>
<script>
(function(){
// ========== 常量与状态 ==========
const PHASES = [
{ name:'静电吸取', dur:2200, title:'PHASE 01 — 静电吸取铜柱' },
{ name:'移至对位', dur:1800, title:'PHASE 02 — 转移头移至对位' },
{ name:'磁场固化', dur:2500, title:'PHASE 03 — 磁场固化 · 柔性漏斗成形' },
{ name:'释放下落', dur:2000, title:'PHASE 04 — 释放静电 · 铜柱下落' },
{ name:'撤磁排液', dur:2200, title:'PHASE 05 — 撤去磁场 · 液化排液' },
{ name:'精准就位', dur:1800, title:'PHASE 06 — 铜柱精准就位' },
];
let currentPhase = 0;
let phaseProgress = 0; // 0~1
let playing = false;
let speed = 1;
let lastTime = 0;
let manualMode = false; // 拖动进度条时
// ========== DOM 元素 ==========
const svg = document.getElementById('scene');
const headGroup = document.getElementById('headGroup');
const pillarGroup = document.getElementById('pillarGroup');
const copperPillar = document.getElementById('copperPillar');
const pillarTop = document.getElementById('pillarTop');
const electroGlow = document.getElementById('electroGlow');
const mrTrough = document.getElementById('mrTrough');
const mrHole = document.getElementById('mrHole');
const funnelGroup = document.getElementById('funnelGroup');
const funnelPulse = document.getElementById('funnelPulse');
const magLines = document.getElementById('magLines');
const calloutVoltage = document.getElementById('calloutVoltage');
const calloutGap = document.getElementById('calloutGap');
const calloutYield = document.getElementById('calloutYield');
const phaseTitleText = document.getElementById('phaseTitleText');
const successMark = document.getElementById('successMark');
const trailGroup = document.getElementById('trailGroup');
const fallTrail = document.getElementById('fallTrail');
const arrayHighlight = document.getElementById('arrayHighlight');
const btnPlay = document.getElementById('btnPlay');
const btnStep = document.getElementById('btnStep');
const btnReset = document.getElementById('btnReset');
const timeline = document.getElementById('timeline');
const phaseSteps = document.querySelectorAll('.phase-step');
const speedBtns = document.querySelectorAll('.speed-btns .btn');
const paramCards = {
voltage: document.getElementById('pcVoltage'),
gap: document.getElementById('pcGap'),
yield: document.getElementById('pcYield'),
ifr: document.getElementById('pcIFR'),
};
// ========== 初始化阵列缩略图 ==========
(function initArrayDots(){
const g = document.getElementById('arrayDots');
const cols = 11, rows = 11, spacing = 11, ox = 14, oy = 27;
for(let r=0;r<rows;r++){
for(let c=0;c<cols;c++){
const dot = document.createElementNS('http://www.w3.org/2000/svg','rect');
dot.setAttribute('x', ox + c*spacing);
dot.setAttribute('y', oy + r*spacing);
dot.setAttribute('width', 4);
dot.setAttribute('height', 4);
dot.setAttribute('rx', 0.8);
dot.setAttribute('fill', 'rgba(0,229,255,0.2)');
g.appendChild(dot);
}
}
})();
// ========== 初始化MR流体粒子 ==========
const mrParticles = [];
(function initParticles(){
const g = document.getElementById('mrParticles');
// 浅槽中的粒子
for(let i=0;i<20;i++){
const c = document.createElementNS('http://www.w3.org/2000/svg','circle');
const x = 230 + Math.random()*340;
const y = 433 + Math.random()*24;
c.setAttribute('cx', x);
c.setAttribute('cy', y);
c.setAttribute('r', 1.5 + Math.random()*1.5);
c.setAttribute('fill', 'rgba(0,210,190,0.25)');
g.appendChild(c);
mrParticles.push({el:c, ox:x, oy:y, baseR:parseFloat(c.getAttribute('r')), zone:'trough'});
}
// 孔内粒子
for(let i=0;i<15;i++){
const c = document.createElementNS('http://www.w3.org/2000/svg','circle');
const x = 395 + Math.random()*10;
const y = 465 + Math.random()*280;
c.setAttribute('cx', x);
c.setAttribute('cy', y);
c.setAttribute('r', 1.2 + Math.random()*1.2);
c.setAttribute('fill', 'rgba(0,210,190,0.25)');
g.appendChild(c);
mrParticles.push({el:c, ox:x, oy:y, baseR:parseFloat(c.getAttribute('r')), zone:'hole'});
}
})();
// ========== 工具函数 ==========
function lerp(a,b,t){ return a + (b-a) * Math.max(0, Math.min(1, t)); }
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; }
function setOp(el, v){ el.setAttribute('opacity', Math.max(0,Math.min(1,v))); }
function setTy(el, dy){ el.setAttribute('transform', 'translate(0,'+dy+')'); }
// ========== 核心渲染 ==========
// 铜柱状态
let pillarDy = 0; // 铜柱相对初始位置的Y偏移
let pillarReleased = false;
let pillarFallProgress = 0;
// 转移头状态
let headDy = 0;
function render(){
const p = currentPhase;
const t = phaseProgress;
const et = easeInOut(t);
// ------ Phase 0: 静电吸取 ------
if(p === 0){
// 静电发光渐入
setOp(electroGlow, et);
// 铜柱微微振动(被吸取的抖动)
const jitter = Math.sin(t * Math.PI * 8) * (1-t) * 2;
setTy(pillarGroup, jitter);
pillarDy = 0;
headDy = 0;
// 标注
setOp(calloutVoltage, et);
setOp(calloutGap, 0);
setOp(calloutYield, 0);
// 参数卡
paramCards.voltage.classList.toggle('visible', t > 0.3);
paramCards.gap.classList.remove('visible');
paramCards.yield.classList.remove('visible');
paramCards.ifr.classList.remove('visible');
// 阵列高亮
setOp(arrayHighlight, et * 0.8);
}
// ------ Phase 1: 移至对位 ------
if(p === 1){
setOp(electroGlow, 1);
setOp(calloutVoltage, 1 - et);
headDy = et * 28; // 下移28px
setTy(headGroup, headDy);
setTy(pillarGroup, headDy);
// 间隙标注渐入
setOp(calloutGap, et);
paramCards.gap.classList.toggle('visible', t > 0.3);
}
// ------ Phase 2: 磁场固化(核心创新) ------
if(p === 2){
setOp(electroGlow, 1);
headDy = 28;
setTy(headGroup, headDy);
setTy(pillarGroup, headDy);
// 磁场线渐入
setOp(magLines, et);
// MR流体从液态到固态
// 浅槽MR流体变浓
mrTrough.setAttribute('fill', 'rgba(0,200,180,'+lerp(0.18,0.4,et)+')');
mrHole.setAttribute('fill', 'rgba(0,200,180,'+lerp(0.22,0.5,et)+')');
// 粒子对齐(从随机到有序)
mrParticles.forEach((pt,i) => {
const alignT = easeOut(Math.max(0, (t - 0.2) / 0.8));
if(pt.zone === 'hole'){
// 孔内粒子排列成垂直线
const alignedX = (i % 2 === 0) ? 396 : 404;
const nx = lerp(pt.ox, alignedX, alignT);
pt.el.setAttribute('cx', nx);
pt.el.setAttribute('fill', 'rgba(0,230,200,'+lerp(0.25,0.6,alignT)+')');
} else {
// 浅槽粒子向孔口聚集
const alignedX = lerp(pt.ox, 395 + (i%3)*5, alignT * 0.6);
pt.el.setAttribute('cx', alignedX);
pt.el.setAttribute('fill', 'rgba(0,230,200,'+lerp(0.25,0.5,alignT)+')');
}
});
// 漏斗出现(关键!)
const funnelT = easeOut(Math.max(0, (t - 0.3) / 0.7));
setOp(funnelGroup, funnelT);
// 漏斗脉冲发光
const pulse = (Math.sin(t * Math.PI * 4) * 0.5 + 0.5) * funnelT;
setOp(funnelPulse, pulse * 0.6);
// 标注
setOp(calloutGap, 1 - et);
setOp(calloutYield, funnelT);
paramCards.yield.classList.toggle('visible', t > 0.4);
paramCards.ifr.classList.toggle('visible', t > 0.6);
}
// ------ Phase 3: 释放下落 ------
if(p === 3){
headDy = 28;
setTy(headGroup, headDy);
// 静电消失
setOp(electroGlow, 1 - et);
// 铜柱释放下落
const fallT = easeIn(t);
const fallDist = fallT * 260; // 下落260px
pillarDy = headDy + fallDist;
setTy(pillarGroup, pillarDy);
// 下落轨迹
setOp(trailGroup, t < 0.8 ? 0.6 : (1-t)*3);
fallTrail.setAttribute('y1', 268 + headDy);
fallTrail.setAttribute('y2', 268 + pillarDy);
// 漏斗引导发光增强
const guideGlow = Math.sin(t * Math.PI) * 0.8;
setOp(funnelPulse, guideGlow);
// 磁场仍保持
setOp(magLines, 1);
setOp(funnelGroup, 1);
setOp(calloutYield, 1 - et * 0.5);
}
// ------ Phase 4: 撤磁排液 ------
if(p === 4){
headDy = 28;
setTy(headGroup, headDy);
// 铜柱在最终位置
pillarDy = 288; // 最终位置
setTy(pillarGroup, pillarDy);
// 静电已关
setOp(electroGlow, 0);
setOp(trailGroup, 0);
// 磁场消失
setOp(magLines, 1 - et);
setOp(funnelGroup, 1 - et);
// MR流体恢复液态
mrTrough.setAttribute('fill', 'rgba(0,200,180,'+lerp(0.4,0.1,et)+')');
mrHole.setAttribute('fill', 'rgba(0,200,180,'+lerp(0.5,0.08,et)+')');
// 粒子恢复随机
mrParticles.forEach((pt) => {
pt.el.setAttribute('cx', lerp(parseFloat(pt.el.getAttribute('cx')), pt.ox, et * 0.5));
pt.el.setAttribute('fill', 'rgba(0,210,190,'+lerp(0.6,0.15,et)+')');
});
// MR流体"流出"效果
const drainT = easeIn(t);
const troughH = lerp(30, 8, drainT);
const troughY = lerp(430, 452, drainT);
mrTrough.setAttribute('y', troughY);
mrTrough.setAttribute('height', troughH);
setOp(calloutYield, 0);
}
// ------ Phase 5: 精准就位 ------
if(p === 5){
headDy = 28;
setTy(headGroup, headDy);
pillarDy = 288;
setTy(pillarGroup, pillarDy);
setOp(electroGlow, 0);
setOp(magLines, 0);
setOp(funnelGroup, 0);
setOp(trailGroup, 0);
setOp(mrParticles, 0);
// MR流体几乎消失
mrTrough.setAttribute('fill', 'rgba(0,200,180,0.05)');
mrHole.setAttribute('fill', 'rgba(0,200,180,0.05)');
// 成功标记出现
setOp(successMark, et);
// 铜柱微微确认闪烁
const confirmPulse = Math.sin(t * Math.PI * 2) * 0.3 + 0.7;
copperPillar.setAttribute('opacity', confirmPulse);
}
// ------ 全局:阶段标题 ------
phaseTitleText.textContent = PHASES[Math.min(p, PHASES.length-1)].title;
// ------ 全局:进度条同步 ------
if(!manualMode){
const totalPhases = PHASES.length;
const globalProgress = (currentPhase + phaseProgress) / totalPhases;
timeline.value = Math.round(globalProgress * 1000);
}
// ------ 全局:阶段指示器 ------
phaseSteps.forEach((el, i) => {
el.classList.remove('active','done');
if(i < currentPhase) el.classList.add('done');
else if(i === currentPhase) el.classList.add('active');
});
}
// ========== 动画循环 ==========
function tick(now){
if(!playing){ lastTime = now; requestAnimationFrame(tick); return; }
if(lastTime === 0) lastTime = now;
const dt = (now - lastTime) * speed;
lastTime = now;
const dur = PHASES[currentPhase].dur;
phaseProgress += dt / dur;
if(phaseProgress >= 1){
phaseProgress = 0;
currentPhase++;
if(currentPhase >= PHASES.length){
currentPhase = PHASES.length - 1;
phaseProgress = 1;
playing = false;
btnPlay.innerHTML = '<i class="fa-solid fa-play"></i> 播放';
}
}
render();
requestAnimationFrame(tick);
}
// ========== 交互控制 ==========
btnPlay.addEventListener('click', () => {
if(playing){
playing = false;
btnPlay.innerHTML = '<i class="fa-solid fa-play"></i> 播放';
} else {
// 如果已完成,重新开始
if(currentPhase >= PHASES.length - 1 && phaseProgress >= 1){
resetAnim();
}
playing = true;
btnPlay.innerHTML = '<i class="fa-solid fa-pause"></i> 暂停';
}
});
btnStep.addEventListener('click', () => {
playing = false;
btnPlay.innerHTML = '<i class="fa-solid fa-play"></i> 播放';
currentPhase = Math.min(currentPhase + 1, PHASES.length - 1);
phaseProgress = 0;
// 快速渲染到该阶段起始状态
renderAtPhaseStart(currentPhase);
// 然后自动播放当前阶段
playing = true;
btnPlay.innerHTML = '<i class="fa-solid fa-pause"></i> 暂停';
});
btnReset.addEventListener('click', resetAnim);
function resetAnim(){
playing = false;
currentPhase = 0;
phaseProgress = 0;
headDy = 0;
pillarDy = 0;
btnPlay.innerHTML = '<i class="fa-solid fa-play"></i> 播放';
// 重置所有元素状态
setTy(headGroup, 0);
setTy(pillarGroup, 0);
setOp(electroGlow, 0);
setOp(magLines, 0);
setOp(funnelGroup, 0);
setOp(funnelPulse, 0);
setOp(successMark, 0);
setOp(trailGroup, 0);
setOp(calloutVoltage, 0);
setOp(calloutGap, 0);
setOp(calloutYield, 0);
setOp(arrayHighlight, 0);
copperPillar.setAttribute('opacity', 1);
mrTrough.setAttribute('fill', 'rgba(0,200,180,0.18)');
mrTrough.setAttribute('y', 430);
mrTrough.setAttribute('height', 30);
mrHole.setAttribute('fill', 'rgba(0,200,180,0.22)');
setOp(mrParticles, 1);
mrParticles.forEach(pt => {
pt.el.setAttribute('cx', pt.ox);
pt.el.setAttribute('cy', pt.oy);
pt.el.setAttribute('fill', 'rgba(0,210,190,0.25)');
});
Object.values(paramCards).forEach(c => c.classList.remove('visible'));
render();
}
// 渲染某阶段起始状态(快速跳转到该阶段前)
function renderAtPhaseStart(targetPhase){
// 先重置
resetAnim();
// 逐阶段快进到目标阶段的起始
currentPhase = targetPhase;
phaseProgress = 0;
// 快速应用之前阶段的终态
for(let i = 0; i < targetPhase; i++){
currentPhase = i;
phaseProgress = 1;
render();
}
currentPhase = targetPhase;
phaseProgress = 0;
}
// 进度条拖动
let draggingTimeline = false;
timeline.addEventListener('mousedown', () => { manualMode = true; draggingTimeline = true; });
timeline.addEventListener('touchstart', () => { manualMode = true; draggingTimeline = true; }, {passive:true});
window.addEventListener('mouseup', () => { draggingTimeline = false; manualMode = false; });
window.addEventListener('touchend', () => { draggingTimeline = false; manualMode = false; });
timeline.addEventListener('input', () => {
playing = false;
btnPlay.innerHTML = '<i class="fa-solid fa-play"></i> 播放';
const val = parseFloat(timeline.value) / 1000;
const totalPhases = PHASES.length;
const rawPhase = val * totalPhases;
currentPhase = Math.min(Math.floor(rawPhase), totalPhases - 1);
phaseProgress = rawPhase - currentPhase;
render();
});
// 速度按钮
speedBtns.forEach(btn => {
btn.addEventListener('click', () => {
speed = parseFloat(btn.dataset.speed);
speedBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
});
});
// ========== 启动 ==========
render();
requestAnimationFrame(tick);
// 自动开始播放(延迟500ms)
setTimeout(() => {
playing = true;
btnPlay.innerHTML = '<i class="fa-solid fa-pause"></i> 暂停';
}, 600);
})();
</script>
</body>
</html>
实现说明
设计美学方向:深空实验室风格(Dark Lab Instrument),深邃的暗蓝黑底色搭配青色(MR流体)与琥珀色(静电场)双主色调,所有标注和参数使用等宽字体,营造精密仪器感。
动画六阶段时序:
| 阶段 | 核心视觉事件 | IFR 体现 |
|---|---|---|
| 01 静电吸取 | 琥珀色电场发光渐亮,铜柱微振被吸 | 资源利用:电场力并行抓取 22500 根 |
| 02 移至对位 | 转移头整体下移 28px,间隙标注出现 | 精确对合 0.05mm |
| 03 磁场固化 | MR 粒子从随机→有序排列,漏斗形发光轮廓成形 | 核心:孔壁自我变为柔性导向,问题自行消失 |
| 04 释放下落 | 静电消隐,铜柱沿漏斗壁滑入,轨迹线显现 | 柔性壁自对准,无硬接触 |
| 05 撤磁排液 | 磁场线消隐,粒子散开,流体变透明流出 | 相变逆转,资源释放 |
| 06 精准就位 | 成功勾号出现,铜柱确认脉冲 | IFR 最终态达成 |
交互控制:播放/暂停、逐阶段步进、重置、进度条拖拽、0.5x/1x/2x 变速,以及底部四张参数卡随阶段联动亮显。
视觉引导重点:Phase 03 的漏斗成形是全动画的"记忆锚点"——粒子从混沌到有序的相变、漏斗轮廓的脉冲发光、50kPa 屈服强度 标注同时出现,将 IFR 思想(刚性孔壁 → 柔性自对准,卡死矛盾自我消灭)可视化到极致。
积分规则:第一轮对话扣减6分,后续每轮扣4分
等待动画代码生成...
