<!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=Rajdhani:wght@400;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
--bg:#060a14;--bg2:#0c1222;--card:#111a2e;--card-b:#1c2a44;
--t1:#e2e8f0;--t2:#8ea4c0;--t3:#546580;
--accent:#00e5ff;--accent2:#00b8d4;--accent-dim:rgba(0,229,255,.12);
--mr-liq:#ff9f43;--mr-sol:#4a9ebb;
--memb:rgba(255,140,155,.6);--pcb:#22c55e;--pcb2:#166534;
--ok:#10b981;--warn:#f59e0b;--err:#ef4444;
}
body{background:var(--bg);color:var(--t1);font-family:'Noto Sans SC',sans-serif;min-height:100vh;display:flex;flex-direction:column;align-items:center;overflow-x:hidden}
.page{width:100%;max-width:1280px;padding:20px 16px 32px}
header{text-align:center;margin-bottom:12px}
header h1{font-family:'Rajdhani',sans-serif;font-weight:700;font-size:clamp(22px,3.2vw,36px);letter-spacing:2px;background:linear-gradient(135deg,var(--accent),#80ffea);-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:4px}
header p{font-size:13px;color:var(--t3);letter-spacing:1px}
.svg-wrap{background:var(--bg2);border:1px solid var(--card-b);border-radius:14px;overflow:hidden;position:relative;margin-bottom:16px}
.svg-wrap svg{display:block;width:100%;height:auto}
.info-row{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.info-card{flex:1;min-width:200px;background:var(--card);border:1px solid var(--card-b);border-radius:10px;padding:14px 16px;transition:border-color .3s}
.info-card.active{border-color:var(--accent)}
.info-card h3{font-family:'Rajdhani',sans-serif;font-size:14px;color:var(--accent);margin-bottom:6px;letter-spacing:1px}
.info-card p{font-size:13px;color:var(--t2);line-height:1.6}
.ifr-tag{display:inline-block;background:linear-gradient(135deg,var(--accent-dim),rgba(0,229,255,.05));border:1px solid rgba(0,229,255,.25);border-radius:4px;padding:2px 8px;font-size:11px;color:var(--accent);margin-top:6px;letter-spacing:.5px}
.ctrl-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
.btn{font-family:'Rajdhani',sans-serif;font-weight:600;font-size:13px;padding:7px 18px;border-radius:7px;border:1px solid var(--card-b);background:var(--card);color:var(--t2);cursor:pointer;transition:all .2s;letter-spacing:.5px;user-select:none}
.btn:hover{border-color:var(--accent);color:var(--t1)}
.btn.active{background:rgba(0,229,255,.1);border-color:var(--accent);color:var(--accent)}
.btn.play{min-width:90px}
.phase-dots{display:flex;gap:6px;align-items:center}
.phase-dot{width:10px;height:10px;border-radius:50%;background:var(--card-b);border:1.5px solid var(--t3);transition:all .3s;cursor:pointer}
.phase-dot.done{background:var(--accent2);border-color:var(--accent)}
.phase-dot.current{background:var(--accent);border-color:var(--accent);box-shadow:0 0 8px var(--accent)}
.slider-group{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--t2)}
.slider-group label{white-space:nowrap;min-width:80px}
.slider-group input[type=range]{-webkit-appearance:none;width:120px;height:4px;background:var(--card-b);border-radius:2px;outline:none}
.slider-group input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;border-radius:50%;background:var(--accent);cursor:pointer;border:none}
.slider-group span{min-width:36px;text-align:right;font-family:'Rajdhani',sans-serif;color:var(--accent)}
.params{display:flex;gap:16px;flex-wrap:wrap;margin-top:12px;padding-top:10px;border-top:1px solid var(--card-b)}
.param{font-size:11px;color:var(--t3)}.param b{color:var(--t2);font-weight:500}
@media(max-width:640px){.info-row{flex-direction:column}.ctrl-row{flex-direction:column;align-items:stretch}}
</style>
</head>
<body>
<div class="page">
<header>
<h1>MAGNETORHEOLOGICAL ADAPTIVE BRACKET</h1>
<p>磁流变柔性自适应托架 · IFR 最终理想解原理动画</p>
</header>
<div class="svg-wrap">
<svg id="mainSvg" viewBox="0 0 1200 680" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 蜂窝图案 -->
<pattern id="honeycomb" x="0" y="0" width="22" height="19" patternUnits="userSpaceOnUse">
<polygon points="11,0 22,5.5 22,13.5 11,19 0,13.5 0,5.5" fill="none" stroke="#556677" stroke-width=".5" opacity=".35"/>
</pattern>
<!-- 铜走线图案 -->
<pattern id="copperTraces" x="0" y="0" width="40" height="18" patternUnits="userSpaceOnUse">
<line x1="0" y1="6" x2="40" y2="6" stroke="#c87533" stroke-width=".8" opacity=".3"/>
<line x1="0" y1="14" x2="40" y2="14" stroke="#c87533" stroke-width=".6" opacity=".2"/>
<circle cx="20" cy="10" r="1.5" fill="#c87533" opacity=".25"/>
</pattern>
<!-- 发光滤镜 -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
</filter>
<filter id="glowStrong" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="blur"/>
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
</filter>
<!-- MR流体渐变(液态) -->
<linearGradient id="mrLiqGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#ffbe76"/>
<stop offset="100%" stop-color="#ff793f"/>
</linearGradient>
<!-- MR流体渐变(固态) -->
<linearGradient id="mrSolGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#5dade2"/>
<stop offset="100%" stop-color="#2e86c1"/>
</linearGradient>
<!-- 流体裁剪 -->
<clipPath id="fluidClip"><path id="fluidClipPath" d=""/></clipPath>
<!-- 磁力线标记 -->
<marker id="arrowCyan" viewBox="0 0 6 6" refX="3" refY="3" markerWidth="4" markerHeight="4" orient="auto">
<path d="M0,0 L6,3 L0,6 Z" fill="#00e5ff" opacity=".6"/>
</marker>
</defs>
<!-- 背景网格 -->
<g opacity=".08">
<line x1="0" y1="340" x2="1200" y2="340" stroke="#00e5ff" stroke-width=".5" stroke-dasharray="4 8"/>
<line x1="600" y1="0" x2="600" y2="680" stroke="#00e5ff" stroke-width=".5" stroke-dasharray="4 8"/>
</g>
<!-- 左侧导轨 -->
<g id="rails" opacity=".5">
<rect x="218" y="120" width="8" height="480" rx="2" fill="#1c2a44" stroke="#2a3a55" stroke-width=".5"/>
<rect x="974" y="120" width="8" height="480" rx="2" fill="#1c2a44" stroke="#2a3a55" stroke-width=".5"/>
<text x="222" y="110" font-size="9" fill="#546580" font-family="Rajdhani" text-anchor="middle">GUIDE</text>
<text x="978" y="110" font-size="9" fill="#546580" font-family="Rajdhani" text-anchor="middle">GUIDE</text>
</g>
<!-- 机械臂横梁 -->
<g id="armCrossbar">
<rect x="210" y="125" width="780" height="14" rx="3" fill="#1a2540" stroke="#2a3a55" stroke-width="1"/>
<rect x="580" y="112" width="40" height="18" rx="4" fill="#0d1825" stroke="#2a3a55" stroke-width="1"/>
<text x="600" y="125" font-size="8" fill="#546580" font-family="Rajdhani" text-anchor="middle">ACTUATOR</text>
</g>
<!-- 连接杆(从横梁到托架) -->
<g id="armConnectors">
<rect id="connL" x="280" y="139" width="6" height="60" rx="1" fill="#1a2540" stroke="#2a3a55" stroke-width=".5"/>
<rect id="connR" x="914" y="139" width="6" height="60" rx="1" fill="#1a2540" stroke="#2a3a55" stroke-width=".5"/>
</g>
<!-- ===== 托架组件组(整体可移动) ===== -->
<g id="bracketGroup">
<!-- 基板 -->
<rect id="basePlate" x="250" y="358" width="700" height="30" rx="2" fill="#8899aa" stroke="#667788" stroke-width="1"/>
<rect id="baseHoneycomb" x="250" y="358" width="700" height="30" rx="2" fill="url(#honeycomb)"/>
<text x="600" y="377" font-size="9" fill="#334455" font-family="Rajdhani" text-anchor="middle" font-weight="600" letter-spacing="2">ALUMINUM HONEYCOMB BASE</text>
<!-- 电磁铁阵列 -->
<g id="electromagnets"></g>
<!-- MR流体区域 -->
<path id="mrFluid" d="" fill="url(#mrLiqGrad)" opacity=".85"/>
<!-- MR流体粒子(在裁剪区内) -->
<g clip-path="url(#fluidClip)">
<g id="mrParticles"></g>
</g>
<!-- 硅胶膜 -->
<path id="membrane" d="" fill="rgba(255,140,155,.22)" stroke="rgba(255,140,155,.7)" stroke-width="2.5"/>
</g>
<!-- ===== PCB组件 ===== -->
<g id="pcbGroup">
<!-- PCB弯曲指示线 -->
<path id="bendLine" d="" fill="none" stroke="#ef4444" stroke-width="1.5" stroke-dasharray="6 4" opacity="0"/>
<!-- PCB板 -->
<rect id="pcbBoard" x="250" y="248" width="700" height="18" rx="1" fill="#166534" stroke="#22c55e" stroke-width=".8"/>
<rect x="250" y="248" width="700" height="18" rx="1" fill="url(#copperTraces)"/>
<text x="600" y="261" font-size="9" fill="#4ade80" font-family="Rajdhani" text-anchor="middle" font-weight="600" letter-spacing="3">PCB — 13kg</text>
<!-- 底部元器件 -->
<g id="components"></g>
</g>
<!-- 均匀支撑力箭头 -->
<g id="forceArrows" opacity="0"></g>
<!-- 磁力线 -->
<g id="fieldLines" opacity="0"></g>
<!-- 标注文字 -->
<g id="annotations" font-family="'Noto Sans SC',sans-serif"></g>
<!-- 相位标签 -->
<g id="phaseLabel" font-family="'Rajdhani',sans-serif">
<rect x="20" y="20" width="200" height="36" rx="6" fill="rgba(0,229,255,.08)" stroke="rgba(0,229,255,.25)" stroke-width="1"/>
<text id="phaseText" x="120" y="43" font-size="14" fill="#00e5ff" text-anchor="middle" font-weight="600" letter-spacing="1"></text>
</g>
<!-- 挠度指示 -->
<g id="deflection" opacity="0" font-family="Rajdhani,sans-serif">
<rect x="980" y="240" width="140" height="30" rx="5" fill="rgba(239,68,68,.1)" stroke="rgba(239,68,68,.3)" stroke-width="1"/>
<text id="deflText" x="1050" y="260" font-size="12" fill="#ef4444" text-anchor="middle" font-weight="600"></text>
</g>
</svg>
</div>
<!-- 信息面板 -->
<div class="info-row">
<div class="info-card" id="cardMech">
<h3>MECHANISM / 核心机理</h3>
<p>磁流变液在磁场下毫秒级固化,使柔性托架瞬间从"液态自适应"转为"刚性定制模具",实现全表面均匀支撑。</p>
<span class="ifr-tag">IFR: 流体自适应 = 自动寻优支撑面</span>
</div>
<div class="info-card" id="cardIFR">
<h3>IFR INSIGHT / 理想解洞察</h3>
<p id="ifrText">等待动画启动…</p>
<span class="ifr-tag" id="ifrTag">—</span>
</div>
<div class="info-card" id="cardParam">
<h3>KEY PARAMS / 关键参数</h3>
<p>固化响应 ≤50ms | 硅胶膜 2mm | 电磁铁间距 20mm</p>
<p style="margin-top:4px;font-size:11px;color:var(--t3)">边界:高温PCB不适用;尖锐元器件可能刺破硅胶膜</p>
</div>
</div>
<!-- 控制面板 -->
<div class="ctrl-row">
<button class="btn play" id="btnPlay" onclick="togglePlay()">▶ 自动播放</button>
<button class="btn" onclick="resetAnim()">↺ 重置</button>
<div class="phase-dots" id="phaseDots"></div>
<div class="slider-group">
<label>磁场强度</label>
<input type="range" id="sliderField" min="0" max="100" value="0" oninput="onFieldSlider(this.value)">
<span id="fieldVal">0%</span>
</div>
<div class="slider-group">
<label>动画速度</label>
<input type="range" id="sliderSpeed" min="25" max="200" value="100" oninput="onSpeedSlider(this.value)">
<span id="speedVal">1.0x</span>
</div>
</div>
<div class="params">
<span class="param">基板: 铝制蜂窝 <b>轻量化</b></span>
<span class="param">填充: 磁流变液 <b>MR Fluid</b></span>
<span class="param">表面: 弹性硅胶膜 <b>2mm</b></span>
<span class="param">阵列: 微型电磁铁 <b>20mm间距</b></span>
</div>
</div>
<script>
/* =========================================
磁流变柔性自适应托架 · IFR原理动画引擎
========================================= */
const SVG_NS = 'http://www.w3.org/2000/svg';
const $ = id => document.getElementById(id);
// ---- 常量 ----
const PCB = { x:250, y:248, w:700, h:18 };
const PCB_BOT = PCB.y + PCB.h; // 266
const COMPS = [
{ x:325, w:55, h:38, label:'电解电容', clr:'#252535', clr2:'#353548' },
{ x:468, w:42, h:18, label:'贴片IC', clr:'#1a1a2e', clr2:'#2a2a40' },
{ x:592, w:68, h:44, label:'功率模块', clr:'#252535', clr2:'#353548' },
{ x:778, w:48, h:24, label:'连接器', clr:'#2a2a28', clr2:'#3a3a35' },
];
const BASE_Y = 358; // 基板顶面(接触位)
const BASE_H = 30;
const BRK_L = PCB.x, BRK_R = PCB.x + PCB.w;
const INIT_OFFSET = 130; // 初始间距
const PHASES = [
{ name:'待机就绪', desc:'柔性托架位于PCB下方待机位', ifr:'准备阶段:托架呈液态柔性', tag:'STANDBY' },
{ name:'下降贴合', desc:'机械手下降,硅胶膜接触PCB底面', ifr:'流体自然贴合——无需计算支撑点', tag:'APPROACH' },
{ name:'自适应塑形', desc:'微抽空气,液态托架完美贴合底部异形轮廓', ifr:'理想解核心:流体自动填充所有间隙,100%吻合', tag:'CONFORM' },
{ name:'磁场固化', desc:'电磁铁通电,磁流变液≤50ms固化成刚性模具', ifr:'无形资源(磁场)瞬间锁定理想形态——极简触发', tag:'SOLIDIFY' },
{ name:'提升取板', desc:'全表面刚性均匀支撑,安全提升无应力集中', ifr:'矛盾消除:柔性适应 + 刚性支撑,同时实现', tag:'LIFT' },
{ name:'释放分离', desc:'到位断电,磁流变液恢复液态,轻松脱模', ifr:'可逆转换:同一资源,按需在柔/刚间切换', tag:'RELEASE' },
];
// ---- 状态 ----
let phase = 0, progress = 0, playing = false, speed = 1;
let fieldStr = 0, conformity = 0, solidify = 0, bracketOff = INIT_OFFSET, liftOff = 0;
let lastTs = 0;
let particles = [];
let animId = null;
// ---- 初始化 ----
function init() {
createComponents();
createElectromagnets();
createParticles();
createPhaseDots();
updateAll();
}
function createComponents() {
const g = $('components');
COMPS.forEach((c,i) => {
const y = PCB_BOT;
// 元器件主体
const r = document.createElementNS(SVG_NS,'rect');
r.setAttribute('x', c.x); r.setAttribute('y', y);
r.setAttribute('width', c.w); r.setAttribute('height', c.h);
r.setAttribute('rx', 2); r.setAttribute('fill', c.clr);
r.setAttribute('stroke', c.clr2); r.setAttribute('stroke-width', '1');
r.id = 'comp'+i;
g.appendChild(r);
// 引脚
const pins = 3 + Math.floor(Math.random()*3);
for(let p=0;p<pins;p++){
const px = c.x + 4 + p * ((c.w-8)/(pins-1));
const ln = document.createElementNS(SVG_NS,'line');
ln.setAttribute('x1',px); ln.setAttribute('y1',y);
ln.setAttribute('x2',px); ln.setAttribute('y2',y+5);
ln.setAttribute('stroke','#888'); ln.setAttribute('stroke-width','1.5');
g.appendChild(ln);
}
// 标签
const t = document.createElementNS(SVG_NS,'text');
t.setAttribute('x', c.x + c.w/2); t.setAttribute('y', y + c.h/2 + 3);
t.setAttribute('font-size','7'); t.setAttribute('fill','#667');
t.setAttribute('text-anchor','middle'); t.setAttribute('font-family','Rajdhani');
t.textContent = c.label;
g.appendChild(t);
});
}
function createElectromagnets() {
const g = $('electromagnets');
const spacing = 35; // 视觉间距
const y = BASE_Y + BASE_H/2;
for(let x = BRK_L + 20; x < BRK_R - 10; x += spacing) {
// 外圈
const c1 = document.createElementNS(SVG_NS,'circle');
c1.setAttribute('cx',x); c1.setAttribute('cy',y);
c1.setAttribute('r',5); c1.setAttribute('fill','none');
c1.setAttribute('stroke','#b87333'); c1.setAttribute('stroke-width','1.2');
c1.classList.add('em-coil');
g.appendChild(c1);
// 内芯
const c2 = document.createElementNS(SVG_NS,'circle');
c2.setAttribute('cx',x); c2.setAttribute('cy',y);
c2.setAttribute('r',2); c2.setAttribute('fill','#8b5e3c');
c2.classList.add('em-core');
g.appendChild(c2);
// 发光圈(初始隐藏)
const c3 = document.createElementNS(SVG_NS,'circle');
c3.setAttribute('cx',x); c3.setAttribute('cy',y);
c3.setAttribute('r',8); c3.setAttribute('fill','none');
c3.setAttribute('stroke','#00e5ff'); c3.setAttribute('stroke-width','1');
c3.setAttribute('opacity','0'); c3.classList.add('em-glow');
g.appendChild(c3);
}
}
function createParticles() {
const g = $('mrParticles');
particles = [];
const count = 70;
for(let i=0;i<count;i++){
const px = BRK_L + 20 + Math.random()*(BRK_R - BRK_L - 40);
const py = PCB_BOT + 10 + Math.random()*80;
const c = document.createElementNS(SVG_NS,'circle');
c.setAttribute('cx',px); c.setAttribute('cy',py);
const r = 1.5 + Math.random()*2.5;
c.setAttribute('r', r);
c.setAttribute('fill','#ffbe76'); c.setAttribute('opacity','0.7');
g.appendChild(c);
particles.push({
el:c, bx:px, by:py, x:px, y:py,
r, vx:(Math.random()-.5)*1.2, vy:(Math.random()-.5)*1.2,
tx:0, ty:0 // 固化目标位置
});
}
// 设置固化目标(网格排列)
const cols = 14, rows = 5;
const gapX = (BRK_R - BRK_L - 40)/cols, gapY = 70/rows;
particles.forEach((p,i) => {
const col = i % cols, row = Math.floor(i/cols) % rows;
p.tx = BRK_L + 20 + col*gapX + gapX/2;
p.ty = PCB_BOT + 15 + row*gapY + gapY/2;
});
}
function createPhaseDots() {
const d = $('phaseDots');
PHASES.forEach((_,i) => {
const dot = document.createElement('div');
dot.className = 'phase-dot'; dot.dataset.idx = i;
dot.onclick = () => jumpToPhase(i);
dot.title = PHASES[i].name;
d.appendChild(dot);
});
}
// ---- 路径生成 ----
function getMembranePath(conf, off) {
// conf: 0=平直 1=完全贴合; off: 托架垂直偏移
const baseY = PCB_BOT + off; // 膜顶部基准
let d = `M ${BRK_L} ${baseY}`;
let cx = BRK_L;
COMPS.forEach(c => {
const compBot = PCB_BOT + c.h;
const targetBot = baseY + c.h * conf;
// 平直段到组件左侧
const ease = 8;
d += ` L ${c.x - ease} ${baseY}`;
// 圆弧下降到组件底部
d += ` C ${c.x} ${baseY}, ${c.x} ${targetBot}, ${c.x + 4} ${targetBot}`;
// 组件底部平直
d += ` L ${c.x + c.w - 4} ${targetBot}`;
// 圆弧上升回基准
d += ` C ${c.x + c.w} ${targetBot}, ${c.x + c.w} ${baseY}, ${c.x + c.w + ease} ${baseY}`;
cx = c.x + c.w + ease;
});
d += ` L ${BRK_R} ${baseY}`;
return d;
}
function getFluidPath(conf, off) {
const baseY = PCB_BOT + off;
const baseInner = BASE_Y + off; // 基板内表面
const memD = getMembranePath(conf, off);
// 膜路径 → 右下角 → 基板底 → 左下角 → 闭合
return memD + ` L ${BRK_R} ${baseInner} L ${BRK_L} ${baseInner} Z`;
}
function getBendPath(amount) {
// PCB弯曲曲线(抛物线近似)
if(amount < 0.01) return `M ${BRK_L} ${PCB_BOT} L ${BRK_R} ${PCB_BOT}`;
const sag = amount * 18; // 最大挠度像素
const mid = (BRK_L + BRK_R)/2;
return `M ${BRK_L} ${PCB_BOT} Q ${mid} ${PCB_BOT + sag} ${BRK_R} ${PCB_BOT}`;
}
// ---- 更新视觉 ----
function updateAll() {
const off = bracketOff - liftOff;
// 托架组位置
$('bracketGroup').setAttribute('transform', `translate(0,${off})`);
// 膜路径(相对于托架组内部坐标,所以不需要off偏移)
// 注意:在bracketGroup内部,坐标是原始坐标,但group整体移动了off
// 所以膜路径的y值应该使用PCB_BOT(接触时的位置),而group的transform负责偏移
const memPath = getMembranePath(conformity, 0);
$('membrane').setAttribute('d', memPath);
// MR流体
const fluidPath = getFluidPath(conformity, 0);
$('mrFluid').setAttribute('d', fluidPath);
$('fluidClipPath').setAttribute('d', fluidPath);
// MR流体颜色(液态→固态渐变)
const liqR=255,liqG=159,liqB=67, solR=74,solG=158,solB=187;
const r=Math.round(liqR+(solR-liqR)*solidify);
const g=Math.round(liqG+(solG-liqG)*solidify);
const b=Math.round(liqB+(solB-liqB)*solidify);
const r2=Math.round(255+(46-255)*solidify);
const g2=Math.round(121+(134-121)*solidify);
const b2=Math.round(63+(193-63)*solidify);
$('mrFluid').setAttribute('fill', `url(#mrLiqGrad)`);
// 动态更新渐变色
const stops = $('mrLiqGrad').querySelectorAll('stop');
stops[0].setAttribute('stop-color',`rgb(${r},${g},${b})`);
stops[1].setAttribute('stop-color',`rgb(${r2},${g2},${b2})`);
// 膜颜色(贴合时略微更不透明)
const membAlpha = .22 + conformity * .15;
const membStroke = .5 + conformity * .3;
$('membrane').setAttribute('fill', `rgba(255,140,155,${membAlpha})`);
$('membrane').setAttribute('stroke', `rgba(255,140,155,${membStroke})`);
// 电磁铁发光
document.querySelectorAll('.em-glow').forEach(el => {
el.setAttribute('opacity', fieldStr * .6);
el.setAttribute('r', 8 + fieldStr * 4);
});
document.querySelectorAll('.em-core').forEach(el => {
if(fieldStr > .3) {
el.setAttribute('fill', `rgb(${Math.round(139+(0-139)*fieldStr)},${Math.round(94+(229-94)*fieldStr)},${Math.round(60+(255-60)*fieldStr)})`);
} else {
el.setAttribute('fill','#8b5e3c');
}
});
// PCB组位置(被提升时)
$('pcbGroup').setAttribute('transform', `translate(0,${-liftOff})`);
// 弯曲指示
const bendAmt = (phase < 4 && phase > 0) ? (1 - conformity * solidify) * 0.6 : (phase === 0 ? 0.8 : 0);
$('bendLine').setAttribute('d', getBendPath(bendAmt));
$('bendLine').setAttribute('opacity', bendAmt > 0.05 ? .7 : 0);
// 挠度指示
const deflMm = (bendAmt * 3.2).toFixed(1);
const deflEl = $('deflection');
if(bendAmt > 0.05) {
deflEl.setAttribute('opacity','1');
$('deflText').textContent = `挠度 ${deflMm}mm`;
$('deflText').setAttribute('fill', bendAmt > .3 ? '#ef4444' : '#f59e0b');
deflEl.querySelector('rect').setAttribute('fill', bendAmt > .3 ? 'rgba(239,68,68,.1)' : 'rgba(245,158,11,.1)');
deflEl.querySelector('rect').setAttribute('stroke', bendAmt > .3 ? 'rgba(239,68,68,.3)' : 'rgba(245,158,11,.3)');
} else {
deflEl.setAttribute('opacity','0');
}
// 力箭头
updateForceArrows();
// 磁力线
updateFieldLines();
// 粒子
updateParticles();
// 连接杆
const bracketTop = BASE_Y + off;
const connH = Math.max(10, bracketTop - 139);
$('connL').setAttribute('height', connH);
$('connR').setAttribute('height', connH);
// 相位标签
$('phaseText').textContent = `${phase+1}/6 — ${PHASES[phase].name}`;
// 信息卡
document.querySelectorAll('.info-card').forEach(c => c.classList.remove('active'));
$('cardIFR').classList.add('active');
$('ifrText').textContent = PHASES[phase].ifr;
$('ifrTag').textContent = PHASES[phase].tag;
// 相位点
document.querySelectorAll('.phase-dot').forEach((d,i) => {
d.classList.toggle('done', i < phase);
d.classList.toggle('current', i === phase);
});
}
function updateForceArrows() {
const g = $('forceArrows');
g.innerHTML = '';
if(solidify < .5) { g.setAttribute('opacity','0'); return; }
g.setAttribute('opacity', String((solidify-.5)*2 * (phase===5? Math.max(0,1-progress*3) : 1)));
const arrowCount = 12;
const spacing = (BRK_R - BRK_L - 40)/(arrowCount-1);
for(let i=0;i<arrowCount;i++){
const ax = BRK_L + 20 + i*spacing;
const ay = PCB_BOT - 6;
const ln = document.createElementNS(SVG_NS,'line');
ln.setAttribute('x1',ax); ln.setAttribute('y1',ay+16);
ln.setAttribute('x2',ax); ln.setAttribute('y2',ay);
ln.setAttribute('stroke','#10b981'); ln.setAttribute('stroke-width','1.5');
ln.setAttribute('marker-end','url(#arrowCyan)');
// 改为绿色箭头
ln.setAttribute('stroke','#10b981');
g.appendChild(ln);
// 箭头尖
const pg = document.createElementNS(SVG_NS,'polygon');
pg.setAttribute('points',`${ax-3},${ay+3} ${ax},${ay-2} ${ax+3},${ay+3}`);
pg.setAttribute('fill','#10b981');
g.appendChild(pg);
}
// 标注
const tx = document.createElementNS(SVG_NS,'text');
tx.setAttribute('x', BRK_L + 10); tx.setAttribute('y', PCB_BOT - 12);
tx.setAttribute('font-size','9'); tx.setAttribute('fill','#10b981');
tx.setAttribute('font-family','Rajdhani'); tx.setAttribute('font-weight','600');
tx.textContent = 'UNIFORM SUPPORT — 0应力集中';
g.appendChild(tx);
}
function updateFieldLines() {
const g = $('fieldLines');
g.innerHTML = '';
if(fieldStr < .05) { g.setAttribute('opacity','0'); return; }
g.setAttribute('opacity', String(fieldStr * .7));
// 从电磁铁向上发出弧形磁力线
const spacing = 70;
const y0 = BASE_Y + BASE_H/2;
for(let x = BRK_L + 50; x < BRK_R - 30; x += spacing){
for(let dy = -1; dy <= 1; dy += 2){
const p = document.createElementNS(SVG_NS,'path');
const h = 30 + fieldStr * 50;
const cx1 = x + dy*15, cy1 = y0 - h*.4;
const cx2 = x + dy*8, cy2 = y0 - h*.8;
p.setAttribute('d',`M ${x} ${y0} C ${cx1} ${cy1}, ${cx2} ${cy2}, ${x+dy*3} ${y0-h}`);
p.setAttribute('fill','none'); p.setAttribute('stroke','#00e5ff');
p.setAttribute('stroke-width', String(.6 + fieldStr*.8));
p.setAttribute('stroke-dasharray','4 3');
p.setAttribute('opacity', String(.3 + fieldStr*.4));
g.appendChild(p);
}
}
}
function updateParticles() {
const t = Date.now() * .001;
particles.forEach(p => {
if(solidify < .1) {
// 液态:布朗运动
p.x += p.vx + Math.sin(t*2 + p.bx)*0.3;
p.y += p.vy + Math.cos(t*1.7 + p.by)*0.3;
// 边界弹回(相对于流体区域)
const minY = PCB_BOT + 5, maxY = BASE_Y - 5;
const minX = BRK_L + 10, maxX = BRK_R - 10;
if(p.x < minX || p.x > maxX) p.vx *= -1;
if(p.y < minY || p.y > maxY) p.vy *= -1;
p.x = Math.max(minX, Math.min(maxX, p.x));
p.y = Math.max(minY, Math.min(maxY, p.y));
} else {
// 固化中:向目标位置移动
const lerpSpeed = .02 + solidify * .08;
p.x += (p.tx - p.x) * lerpSpeed;
p.y += (p.ty - p.y) * lerpSpeed;
}
p.el.setAttribute('cx', p.x);
p.el.setAttribute('cy', p.y);
// 颜色
const liqC = [255,190,118], solC = [93,173,226];
const cr = Math.round(liqC[0]+(solC[0]-liqC[0])*solidify);
const cg = Math.round(liqC[1]+(solC[1]-liqC[1])*solidify);
const cb = Math.round(liqC[2]+(solC[2]-liqC[2])*solidify);
p.el.setAttribute('fill',`rgb(${cr},${cg},${cb})`);
p.el.setAttribute('opacity', .5 + solidify * .4);
});
}
// ---- 动画循环 ----
function animate(ts) {
if(!lastTs) lastTs = ts;
const dt = Math.min((ts - lastTs)/1000, .05) * speed;
lastTs = ts;
if(playing) {
progress += dt * .35;
if(progress >= 1) {
progress = 0;
if(phase < 5) { phase++; }
else { playing = false; progress = 1; updatePlayBtn(); }
}
applyPhase();
} else {
// 即使暂停,粒子仍需更新(液态时)
updateParticles();
}
updateAll();
animId = requestAnimationFrame(animate);
}
function applyPhase() {
const t = easeInOut(progress);
switch(phase) {
case 0: // 待机
bracketOff = INIT_OFFSET;
conformity = 0; solidify = 0; fieldStr = 0; liftOff = 0;
break;
case 1: // 下降贴合
bracketOff = INIT_OFFSET * (1 - t);
conformity = 0; solidify = 0; fieldStr = 0; liftOff = 0;
break;
case 2: // 自适应塑形
bracketOff = 0;
conformity = t;
solidify = 0; fieldStr = 0; liftOff = 0;
break;
case 3: // 磁场固化
bracketOff = 0; conformity = 1;
solidify = t; fieldStr = t;
liftOff = 0;
break;
case 4: // 提升取板
bracketOff = 0; conformity = 1;
solidify = 1; fieldStr = 1;
liftOff = t * 80;
break;
case 5: // 释放分离
bracketOff = 0; conformity = 1;
solidify = Math.max(0, 1 - t*2.5);
fieldStr = Math.max(0, 1 - t*2.5);
liftOff = 80;
if(t > .4) {
conformity = Math.max(0, 1 - (t-.4)*1.8);
bracketOff = (t-.4) * 60;
}
break;
}
// 同步滑块
$('sliderField').value = Math.round(fieldStr*100);
$('fieldVal').textContent = Math.round(fieldStr*100)+'%';
}
function easeInOut(t) {
return t < .5 ? 2*t*t : 1 - Math.pow(-2*t+2,2)/2;
}
// ---- 控制 ----
function togglePlay() {
playing = !playing;
if(playing && phase >= 5 && progress >= 1) {
phase = 0; progress = 0;
}
updatePlayBtn();
}
function updatePlayBtn() {
const btn = $('btnPlay');
btn.textContent = playing ? '⏸ 暂停' : '▶ 自动播放';
btn.classList.toggle('active', playing);
}
function resetAnim() {
playing = false; phase = 0; progress = 0;
bracketOff = INIT_OFFSET; conformity = 0; solidify = 0; fieldStr = 0; liftOff = 0;
updatePlayBtn();
// 重置粒子位置
particles.forEach(p => {
p.x = p.bx; p.y = p.by;
p.vx = (Math.random()-.5)*1.2;
p.vy = (Math.random()-.5)*1.2;
});
updateAll();
}
function jumpToPhase(idx) {
phase = idx; progress = 0; playing = false;
// 快速设置该相位初始状态
switch(idx) {
case 0: bracketOff=INIT_OFFSET; conformity=0; solidify=0; fieldStr=0; liftOff=0; break;
case 1: bracketOff=INIT_OFFSET; conformity=0; solidify=0; fieldStr=0; liftOff=0; break;
case 2: bracketOff=0; conformity=0; solidify=0; fieldStr=0; liftOff=0; break;
case 3: bracketOff=0; conformity=1; solidify=0; fieldStr=0; liftOff=0; break;
case 4: bracketOff=0; conformity=1; solidify=1; fieldStr=1; liftOff=0; break;
case 5: bracketOff=0; conformity=1; solidify=1; fieldStr=1; liftOff=80; break;
}
updatePlayBtn();
updateAll();
}
function onFieldSlider(v) {
fieldStr = v/100;
// 如果在固化阶段,同步solidify
if(phase === 3 || phase === 4) {
solidify = fieldStr;
}
$('fieldVal').textContent = v+'%';
updateAll();
}
function onSpeedSlider(v) {
speed = v/100;
$('speedVal').textContent = speed.toFixed(1)+'x';
}
// ---- 启动 ----
init();
animId = requestAnimationFrame(animate);
</script>
</body>
</html>
这段代码实现了一个完整的磁流变柔性自适应托架 IFR 原理动画,以下是关键设计说明:
视觉设计
- 深色工程美学风格,以青色(#00e5ff)为核心强调色
- MR流体液态呈暖琥珀色,固化后过渡为冷钢蓝色,粒子同步从布朗运动转为有序排列
- 硅胶膜以半透明粉色呈现,贴合度越高越不透明,直观表达"塑形完成"
- 电磁铁激活时产生青色辉光和磁力线弧,磁场强度与滑块联动
IFR 原理聚焦
- 直接展示理想解运行过程,无传统方案对比
- Phase 2(自适应塑形)突出"流体自动填充所有间隙"——无需计算支撑点
- Phase 3(磁场固化)强调"无形资源瞬间锁定"——极简触发
- Phase 4(提升取板)显示均匀支撑力箭头 + "0应力集中"标注
- 弯曲指示线 + 挠度数值实时显示变形消除过程
交互控制
- 6相位自动播放/暂停,可点击相位圆点跳转
- 磁场强度滑块可手动控制固化程度,实时影响粒子行为和颜色
- 动画速度可调(0.25x ~ 2.0x)
- 粒子系统70个粒子,液态布朗运动 → 固态网格对齐,流畅过渡
积分规则:第一轮对话扣减6分,后续每轮扣4分
等待动画代码生成...
