分享图
动画工坊
引擎就绪
<!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=Noto+Sans+SC:wght@300;400;700;900&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<style>
:root{--bg:#0b1120;--fg:#d8e2f0;--muted:#5a6a8a;--accent:#ff9100;--accent2:#00e5ff;--card:#101b30;--border:#1c2c4a;--danger:#ff3d00;--success:#00e676}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--fg);font-family:'Noto Sans SC',sans-serif;min-height:100vh;display:flex;flex-direction:column;align-items:center;overflow-x:hidden}
header{text-align:center;padding:24px 20px 10px;width:100%}
header h1{font-size:clamp(18px,2.4vw,30px);font-weight:900;letter-spacing:1.5px;background:linear-gradient(135deg,var(--accent2),var(--accent));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
header p{font-size:clamp(11px,1.2vw,14px);color:var(--muted);margin-top:6px;font-weight:300;letter-spacing:.5px}
.svg-wrap{width:96%;max-width:1500px;flex:1;display:flex;justify-content:center;align-items:center;min-height:0}
.svg-wrap svg{width:100%;height:auto;max-height:78vh;display:block}
.controls{width:96%;max-width:900px;padding:14px 24px;display:flex;gap:36px;justify-content:center;flex-wrap:wrap;background:var(--card);border-radius:10px;border:1px solid var(--border);margin:8px 0 18px}
.ctrl{display:flex;flex-direction:column;align-items:center;gap:5px}
.ctrl label{font-size:12px;color:var(--muted);font-family:'JetBrains Mono',monospace;letter-spacing:.5px}
.ctrl .val{font-size:15px;font-weight:700;font-family:'JetBrains Mono',monospace}
.val.freq-val{color:var(--accent2)}
.val.press-val{color:var(--accent)}
input[type=range]{-webkit-appearance:none;width:180px;height:5px;border-radius:3px;outline:none;background:var(--border)}
input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;cursor:pointer}
#freqSlider::-webkit-slider-thumb{background:var(--accent2);box-shadow:0 0 8px rgba(0,229,255,.5)}
#pressSlider::-webkit-slider-thumb{background:var(--accent);box-shadow:0 0 8px rgba(255,145,0,.5)}
@media(max-width:700px){.controls{gap:16px;padding:10px 12px}input[type=range]{width:130px}}
</style>
</head>
<body>
<header>
<h1>柔性壁面亥姆霍兹共振器 · 最终理想解</h1>
<p>声波反相抵消 + 柔性壁面自适应调谐 → 低频脉动自消除</p>
</header>
<div class="svg-wrap">
<svg id="svg" viewBox="0 0 1400 850" xmlns="http://www.w3.org/2000/svg"></svg>
</div>
<div class="controls">
<div class="ctrl">
<label>脉动频率 (Hz)</label>
<input type="range" id="freqSlider" min="0.3" max="2.5" step="0.05" value="1.0">
<span class="val freq-val" id="freqVal">1.00</span>
</div>
<div class="ctrl">
<label>内部压力系数</label>
<input type="range" id="pressSlider" min="0.1" max="1.0" step="0.05" value="0.5">
<span class="val press-val" id="pressVal">0.50</span>
</div>
</div>

<script>
/* ====== 配置 ====== */
const NS='http://www.w3.org/2000/svg';
const DUCT={x:90,y:275,w:1220,h:86,wall:7};
const DUCT_CY=DUCT.y+DUCT.h/2;
const RES_CX=[370,700,1030];
const NECK_W=22,NECK_H=48;
const CAV_W=150,CAV_H=165,CAV_R=14;
const CAV_TOP=DUCT.y+DUCT.h+NECK_H;
const CAV_BOT=CAV_TOP+CAV_H;
const CORRUG_COUNT=9,CORRUG_AMP=5;
const MAX_PARTICLES=90;

/* ====== 状态 ====== */
let freq=1.0,press=0.5,time=0;
let particles=[];
let elWaveSegs=[],elCavWaves=[],elNeckParticles=[];
let elFlexWalls=[],elCavGlows=[],elHeatGlows=[];
let elAntiWave1,elAntiWave2,elResultWave;

/* ====== SVG辅助 ====== */
function ce(tag,a={}){const e=document.createElementNS(NS,tag);for(const[k,v]of Object.entries(a))e.setAttribute(k,v);return e}
function sa(el,a){for(const[k,v]of Object.entries(a))el.setAttribute(k,v)}

/* ====== 构建静态结构 ====== */
function build(svg){
  /* --- defs --- */
  const defs=ce('defs');

  // 背景渐变
  const bgGrad=ce('linearGradient',{id:'bgG',x1:'0',y1:'0',x2:'0',y2:'1'});
  bgGrad.append(ce('stop',{offset:'0%','stop-color':'#0d1526'}));
  bgGrad.append(ce('stop',{offset:'100%','stop-color':'#060a14'}));
  defs.append(bgGrad);

  // 柔性壁面发光
  const flexGlow=ce('filter',{id:'flexGlow',x:'-50%',y:'-50%',width:'200%',height:'200%'});
  flexGlow.append(ce('feGaussianBlur',{in:'SourceGraphic',stdDeviation:'4',result:'b'}));
  flexGlow.append(ce('feComposite',{in:'SourceGraphic',in2:'b',operator:'over'}));
  defs.append(flexGlow);

  // 脉动能量发光
  const heatGlow=ce('filter',{id:'heatGlow',x:'-80%',y:'-80%',width:'260%',height:'260%'});
  heatGlow.append(ce('feGaussianBlur',{in:'SourceGraphic',stdDeviation:'8',result:'b'}));
  heatGlow.append(ce('feComposite',{in:'SourceGraphic',in2:'b',operator:'over'}));
  defs.append(heatGlow);

  // 波发光
  const waveGlow=ce('filter',{id:'waveGlow',x:'-10%',y:'-40%',width:'120%',height:'180%'});
  waveGlow.append(ce('feGaussianBlur',{in:'SourceGraphic',stdDeviation:'3',result:'b'}));
  waveGlow.append(ce('feComposite',{in:'SourceGraphic',in2:'b',operator:'over'}));
  defs.append(waveGlow);

  // 柔性壁面渐变
  const flexGrad=ce('linearGradient',{id:'flexG',x1:'0',y1:'0',x2:'0',y2:'1'});
  flexGrad.append(ce('stop',{offset:'0%','stop-color':'#ffb74d'}));
  flexGrad.append(ce('stop',{offset:'50%','stop-color':'#ff9100'}));
  flexGrad.append(ce('stop',{offset:'100%','stop-color':'#e65100'}));
  defs.append(flexGrad);

  // 管道内壁渐变
  const ductInner=ce('linearGradient',{id:'ductIn',x1:'0',y1:'0',x2:'0',y2:'1'});
  ductInner.append(ce('stop',{offset:'0%','stop-color':'#0c1525'}));
  ductInner.append(ce('stop',{offset:'50%','stop-color':'#0f1a2e'}));
  ductInner.append(ce('stop',{offset:'100%','stop-color':'#0c1525'}));
  defs.append(ductInner);

  // 腔体内部渐变
  const cavGrad=ce('linearGradient',{id:'cavG',x1:'0',y1:'0',x2:'0',y2:'1'});
  cavGrad.append(ce('stop',{offset:'0%','stop-color':'#0e1828'}));
  cavGrad.append(ce('stop',{offset:'100%','stop-color':'#0a1220'}));
  defs.append(cavGrad);

  svg.append(defs);

  /* --- 背景 --- */
  svg.append(ce('rect',{x:0,y:0,width:1400,height:850,fill:'url(#bgG)'}));
  // 细网格
  const gridG=ce('g',{opacity:'0.04','stroke':'#4488cc','stroke-width':'0.5'});
  for(let x=0;x<=1400;x+=40)gridG.append(ce('line',{x1:x,y1:0,x2:x,y2:850}));
  for(let y=0;y<=850;y+=40)gridG.append(ce('line',{x1:0,y1:y,x2:1400,y2:y}));
  svg.append(gridG);

  /* --- 主排气管道 --- */
  const ductG=ce('g');
  // 管道外壁
  ductG.append(ce('rect',{x:DUCT.x,y:DUCT.y,width:DUCT.w,height:DUCT.h,rx:6,fill:'#1e2d4a',stroke:'#2e4268','stroke-width':DUCT.wall}));
  // 管道内壁
  ductG.append(ce('rect',{x:DUCT.x+DUCT.wall,y:DUCT.y+DUCT.wall,width:DUCT.w-DUCT.wall*2,height:DUCT.h-DUCT.wall*2,rx:2,fill:'url(#ductIn)'}));
  svg.append(ductG);

  /* --- 共振器结构 --- */
  RES_CX.forEach((cx,i)=>{
    const rG=ce('g');

    // 短颈
    const neckX=cx-NECK_W/2;
    const neckY=DUCT.y+DUCT.h-DUCT.wall;
    rG.append(ce('rect',{x:neckX,y:neckY,width:NECK_W,height:NECK_H+DUCT.wall,fill:'#1e2d4a',stroke:'#2e4268','stroke-width':3}));
    rG.append(ce('rect',{x:neckX+3,y:neckY+3,width:NECK_W-6,height:NECK_H+DUCT.wall-6,fill:'#0e1828',rx:1}));

    // 腔体 (不含柔性壁面 - 后面动态添加)
    // 底部刚性壁
    rG.append(ce('rect',{x:cx-CAV_W/2,y:CAV_BOT-6,width:CAV_W,height:10,rx:5,fill:'#2e4268'}));
    // 腔体内部背景
    rG.append(ce('rect',{x:cx-CAV_W/2+4,y:CAV_TOP+2,width:CAV_W-8,height:CAV_H-8,rx:CAV_R-2,fill:'url(#cavG)',opacity:0.6}));

    svg.append(rG);
  });

  /* --- 标注 --- */
  const lblG=ce('g',{'font-family':"'Noto Sans SC',sans-serif"});
  // 入口标注
  const inletLbl=ce('text',{x:DUCT.x+20,y:DUCT_CY+5,fill:'#ff6e40','font-size':'13','font-weight':'700'});
  inletLbl.textContent='← 来自排气阀';
  lblG.append(inletLbl);
  // 出口标注
  const outletLbl=ce('text',{x:DUCT.x+DUCT.w-140,y:DUCT_CY+5,fill:'#00e676','font-size':'13','font-weight':'700'});
  outletLbl.textContent='净化气流排入壳体 →';
  lblG.append(outletLbl);

  // 各共振器标注
  RES_CX.forEach((cx,i)=>{
    // 短颈直径标注
    const dLbl=ce('text',{x:cx+NECK_W/2+6,y:DUCT.y+DUCT.h+NECK_H/2+4,fill:'#4dd0e1','font-size':'10','font-family':"'JetBrains Mono',monospace"});
    dLbl.textContent='d=2.5mm';
    lblG.append(dLbl);
    // 级数标注
    const sLbl=ce('text',{x:cx,y:CAV_BOT+24,fill:'#5a6a8a','font-size':'11','text-anchor':'middle','font-weight':'700'});
    sLbl.textContent=`第 ${i+1} 级共振器`;
    lblG.append(sLbl);
  });

  // 柔性壁面标注 (高亮 - 核心创新)
  const innovLbl=ce('text',{x:RES_CX[0]-CAV_W/2-8,y:CAV_TOP+CAV_H/2-8,fill:'#ff9100','font-size':'12','font-weight':'900','text-anchor':'end',opacity:'0.95'});
  innovLbl.textContent='柔性壁面';
  lblG.append(innovLbl);
  const innovSub=ce('text',{x:RES_CX[0]-CAV_W/2-8,y:CAV_TOP+CAV_H/2+10,fill:'#ff9100','font-size':'9','text-anchor':'end',opacity:'0.7'});
  innovSub.textContent='0.3mm · 自适应调谐';
  lblG.append(innovSub);

  // 反相抵消标注
  const antiLbl=ce('text',{x:RES_CX[1],y:CAV_TOP+22,fill:'#00e5ff','font-size':'11','text-anchor':'middle','font-weight':'700',opacity:'0.85'});
  antiLbl.textContent='气柱共振 · 反相抵消';
  lblG.append(antiLbl);

  // IFR标注
  const ifrLbl=ce('text',{x:700,y:52,fill:'#ff9100','font-size':'15','text-anchor':'middle','font-weight':'900',opacity:'0.25',letterSpacing:'6'});
  ifrLbl.textContent='IDEAL FINAL RESULT';
  lblG.append(ifrLbl);
  const ifrSub=ce('text',{x:700,y:72,fill:'#ff9100','font-size':'11','text-anchor':'middle','font-weight':'300',opacity:'0.2',letterSpacing:'2'});
  ifrSub.textContent='脉动自消除 — 无需额外能量输入';
  lblG.append(ifrSub);

  svg.append(lblG);

  /* --- 反相声波叠加演示区 --- */
  const demoG=ce('g',{transform:'translate(1060,660)'});
  demoG.append(ce('rect',{x:0,y:0,width:300,height:155,rx:8,fill:'#0a1020',stroke:'#1c2c4a','stroke-width':1,opacity:'0.85'}));
  // 标题
  const demoTitle=ce('text',{x:150,y:18,fill:'#8a9ab0','font-size':'10','text-anchor':'middle','font-weight':'700','font-family':"'Noto Sans SC',sans-serif"});
  demoTitle.textContent='反相叠加消声原理';
  demoG.append(demoTitle);
  // 行标签
  const rowLabels=[
    {y:38,text:'原脉动声波',color:'#ff5722'},
    {y:78,text:'共振器反相声波',color:'#00e5ff'},
    {y:128,text:'叠加结果',color:'#00e676'}
  ];
  rowLabels.forEach(rl=>{
    const t=ce('text',{x:8,y:rl.y+4,fill:rl.color,'font-size':'9','font-family':"'Noto Sans SC',sans-serif",'font-weight':'600',opacity:'0.9'});
    t.textContent=rl.text;
    demoG.append(t);
  });
  svg.append(demoG);

  return{demoG};
}

/* ====== 构建动态元素 ====== */
function buildDynamic(svg,demoG){
  /* --- 波段路径 --- */
  const waveColors=['#ff5722','#ff8a65','#4dd0e1','#00e676'];
  const segBounds=[
    [DUCT.x+DUCT.wall+10,RES_CX[0]-NECK_W/2-8],
    [RES_CX[0]+NECK_W/2+8,RES_CX[1]-NECK_W/2-8],
    [RES_CX[1]+NECK_W/2+8,RES_CX[2]-NECK_W/2-8],
    [RES_CX[2]+NECK_W/2+8,DUCT.x+DUCT.w-DUCT.wall-10]
  ];
  segBounds.forEach((b,i)=>{
    // 波形填充区域
    const fillPath=ce('path',{fill:waveColors[i],opacity:'0.08'});
    svg.appendChild(fillPath);
    // 波形线
    const linePath=ce('path',{fill:'none',stroke:waveColors[i],'stroke-width':'2.5','stroke-linecap':'round',filter:'url(#waveGlow)',opacity:'0.9'});
    svg.appendChild(linePath);
    elWaveSegs.push({fill:fillPath,line:linePath,bounds:b,baseAmp:[32,20,10,3][i]});
  });

  /* --- 腔体内反相波 --- */
  RES_CX.forEach((cx,i)=>{
    const p=ce('path',{fill:'none',stroke:'#00e5ff','stroke-width':'1.8','stroke-linecap':'round',opacity:'0.65'});
    svg.appendChild(p);
    elCavWaves.push({el:p,cx});
  });

  /* --- 短颈粒子 --- */
  RES_CX.forEach((cx,i)=>{
    const pts=[];
    for(let j=0;j<6;j++){
      const c=ce('circle',{r:2.5,fill:'#4dd0e1',opacity:'0.8'});
      svg.appendChild(c);
      pts.push(c);
    }
    elNeckParticles.push({pts,cx});
  });

  /* --- 柔性壁面路径 --- */
  RES_CX.forEach((cx,i)=>{
    const lPath=ce('path',{fill:'none',stroke:'url(#flexG)','stroke-width':'3','stroke-linecap':'round',filter:'url(#flexGlow)'});
    const rPath=ce('path',{fill:'none',stroke:'url(#flexG)','stroke-width':'3','stroke-linecap':'round',filter:'url(#flexGlow)'});
    svg.appendChild(lPath);
    svg.appendChild(rPath);
    elFlexWalls.push({l:lPath,r:rPath,cx});
  });

  /* --- 腔体发光 --- */
  RES_CX.forEach((cx,i)=>{
    const g=ce('ellipse',{cx,cy:CAV_TOP+CAV_H/2,rx:CAV_W/2-10,ry:CAV_H/2-10,fill:'#ff6d00',opacity:'0',filter:'url(#heatGlow)'});
    svg.appendChild(g);
    elCavGlows.push(g);
  });

  /* --- 热能耗散指示 --- */
  RES_CX.forEach((cx,i)=>{
    const g=ce('text',{x:cx+CAV_W/2+12,y:CAV_TOP+CAV_H/2,fill:'#ff6d00','font-size':'10','font-family':"'JetBrains Mono',monospace",opacity:'0'});
    g.textContent='→ 热';
    svg.appendChild(g);
    elHeatGlows.push(g);
  });

  /* --- 气流粒子 --- */
  for(let i=0;i<MAX_PARTICLES;i++){
    const c=ce('circle',{r:1.5+Math.random()*1.5,fill:'#4dd0e1',opacity:0.15+Math.random()*0.35});
    svg.appendChild(c);
    particles.push({
      el:c,
      x:DUCT.x+DUCT.wall+Math.random()*(DUCT.w-DUCT.wall*2),
      y:DUCT_CY+(Math.random()-0.5)*(DUCT.h-DUCT.wall*2-16),
      vx:30+Math.random()*60,
      phase:Math.random()*Math.PI*2
    });
  }

  /* --- 反相叠加演示波形 --- */
  const demoW=280,demoX0=18;
  // 原脉动波
  elAntiWave1=ce('path',{fill:'none',stroke:'#ff5722','stroke-width':'1.5',opacity:'0.85'});
  demoG.appendChild(elAntiWave1);
  // 反相声波
  elAntiWave2=ce('path',{fill:'none',stroke:'#00e5ff','stroke-width':'1.5',opacity:'0.85'});
  demoG.appendChild(elAntiWave2);
  // 叠加结果
  elResultWave=ce('path',{fill:'none',stroke:'#00e676','stroke-width':'2',opacity:'0.9'});
  demoG.appendChild(elResultWave);

  // 中心线
  [38,78,128].forEach(yy=>{
    demoG.appendChild(ce('line',{x1:demoX0,y1:yy,x2:demoX0+demoW,y2:yy,stroke:'#1c2c4a','stroke-width':'0.5','stroke-dasharray':'3,3'}));
  });
}

/* ====== 波形计算 ====== */
function computeWave(x0,x1,yCenter,amp,freqVal,phase0,steps){
  const pts=[];
  for(let i=0;i<=steps;i++){
    const t=i/steps;
    const x=x0+(x1-x0)*t;
    const y=yCenter+amp*Math.sin(2*Math.PI*freqVal*t*3+phase0);
    pts.push({x,y});
  }
  return pts;
}
function ptsToLine(pts){
  if(pts.length<2)return'';
  let d=`M${pts[0].x.toFixed(1)},${pts[0].y.toFixed(1)}`;
  for(let i=1;i<pts.length;i++)d+=` L${pts[i].x.toFixed(1)},${pts[i].y.toFixed(1)}`;
  return d;
}
function ptsToFill(pts,yCenter){
  if(pts.length<2)return'';
  let d=`M${pts[0].x.toFixed(1)},${yCenter.toFixed(1)}`;
  pts.forEach(p=>d+=` L${p.x.toFixed(1)},${p.y.toFixed(1)}`);
  d+=` L${pts[pts.length-1].x.toFixed(1)},${yCenter.toFixed(1)}Z`;
  return d;
}

/* ====== 柔性壁面路径 ====== */
function corrugPath(baseX,yTop,yBot,amp,count,expansion){
  const segH=(yBot-yTop)/(count*2);
  let d=`M${(baseX+expansion).toFixed(1)},${yTop.toFixed(1)}`;
  for(let i=0;i<count*2;i++){
    const ny=yTop+segH*(i+1);
    const nx=baseX+(i%2===0?amp+expansion:-amp+expansion);
    d+=` L${nx.toFixed(1)},${ny.toFixed(1)}`;
  }
  return d;
}

/* ====== 动画更新 ====== */
function update(dt){
  time+=dt;
  const phase0=-time*freq*Math.PI*2;

  /* --- 管道内波形 --- */
  elWaveSegs.forEach((seg,i)=>{
    const amp=seg.baseAmp*(0.7+0.3*press);
    const pts=computeWave(seg.bounds[0],seg.bounds[1],DUCT_CY,amp,freq,phase0,80);
    seg.line.setAttribute('d',ptsToLine(pts));
    seg.fill.setAttribute('d',ptsToFill(pts,DUCT_CY));
  });

  /* --- 腔体内反相波 --- */
  elCavWaves.forEach((cw,i)=>{
    const localPhase=phase0+Math.PI; // 反相
    const amp=12*(0.6+0.4*press);
    const x0=cw.cx-CAV_W/2+14;
    const x1=cw.cx+CAV_W/2-14;
    const yC=CAV_TOP+CAV_H/2;
    const pts=computeWave(x0,x1,yC,amp,freq*0.8,localPhase,50);
    cw.el.setAttribute('d',ptsToLine(pts));
  });

  /* --- 短颈粒子振荡 --- */
  elNeckParticles.forEach((np,i)=>{
    const neckTop=DUCT.y+DUCT.h;
    const neckBot=CAV_TOP;
    const neckCY=(neckTop+neckBot)/2;
    const oscillation=Math.sin(phase0+Math.PI+i*0.3)*NECK_H*0.3*press;
    np.pts.forEach((p,j)=>{
      const baseY=neckCY+(j-2.5)*6;
      const y=baseY+oscillation*Math.cos(j*0.5+time*3);
      const x=np.cx+(Math.random()-0.5)*6;
      sa(p,{cx:x.toFixed(1),cy:y.toFixed(1),opacity:(0.5+0.3*Math.abs(Math.sin(phase0+i))).toFixed(2)});
    });
  });

  /* --- 柔性壁面变形 --- */
  const wallExpansion=press*4*Math.sin(phase0);
  elFlexWalls.forEach((fw,i)=>{
    const localExp=wallExpansion*Math.sin(phase0+i*0.8)*press;
    const leftX=fw.cx-CAV_W/2+3;
    const rightX=fw.cx+CAV_W/2-3;
    fw.l.setAttribute('d',corrugPath(leftX,CAV_TOP+6,CAV_BOT-6,CORRUG_AMP,CORRUG_COUNT,-localExp));
    fw.r.setAttribute('d',corrugPath(rightX,CAV_TOP+6,CAV_BOT-6,CORRUG_AMP,CORRUG_COUNT,localExp));
  });

  /* --- 腔体发光 (能量耗散) --- */
  elCavGlows.forEach((g,i)=>{
    const intensity=0.08+0.12*Math.abs(Math.sin(phase0+i*0.6))*press;
    sa(g,{opacity:intensity.toFixed(3)});
  });

  /* --- 热能耗散文字 --- */
  elHeatGlows.forEach((g,i)=>{
    const opacity=0.3+0.5*Math.abs(Math.sin(phase0+i*0.6))*press;
    g.setAttribute('opacity',opacity.toFixed(2));
  });

  /* --- 气流粒子 --- */
  particles.forEach(p=>{
    p.x+=p.vx*dt;
    // 加微小波动
    p.y+=Math.sin(time*2+p.phase)*0.3;
    // 边界循环
    const xMax=DUCT.x+DUCT.w-DUCT.wall-4;
    const xMin=DUCT.x+DUCT.wall+4;
    if(p.x>xMax){p.x=xMin;p.y=DUCT_CY+(Math.random()-0.5)*(DUCT.h-DUCT.wall*2-16);}
    const yMin=DUCT.y+DUCT.wall+4;
    const yMax=DUCT.y+DUCT.h-DUCT.wall-4;
    if(p.y<yMin)p.y=yMin;
    if(p.y>yMax)p.y=yMax;
    sa(p.el,{cx:p.x.toFixed(1),cy:p.y.toFixed(1)});
  });

  /* --- 反相叠加演示 --- */
  const dW=270,dX0=22;
  const demoAmp1=12,demoAmp2=12;
  // 原脉动波 (第1行, y=38)
  const d1=[];
  for(let i=0;i<=80;i++){
    const t=i/80;
    const x=dX0+dW*t;
    const y=38+demoAmp1*Math.sin(2*Math.PI*freq*t*3+phase0);
    d1.push({x,y});
  }
  elAntiWave1.setAttribute('d',ptsToLine(d1));
  // 反相声波 (第2行, y=78)
  const d2=[];
  for(let i=0;i<=80;i++){
    const t=i/80;
    const x=dX0+dW*t;
    const y=78+demoAmp2*Math.sin(2*Math.PI*freq*t*3+phase0+Math.PI);
    d2.push({x,y});
  }
  elAntiWave2.setAttribute('d',ptsToLine(d2));
  // 叠加结果 (第3行, y=128)
  const d3=[];
  for(let i=0;i<=80;i++){
    const t=i/80;
    const x=dX0+dW*t;
    const v1=demoAmp1*Math.sin(2*Math.PI*freq*t*3+phase0);
    const v2=demoAmp2*Math.sin(2*Math.PI*freq*t*3+phase0+Math.PI);
    const y=128+(v1+v2)*0.15; // 近乎为零
    d3.push({x,y});
  }
  elResultWave.setAttribute('d',ptsToLine(d3));
}

/* ====== 动画循环 ====== */
let lastT=0;
function loop(ts){
  if(!lastT)lastT=ts;
  const dt=Math.min((ts-lastT)/1000,0.05);
  lastT=ts;
  update(dt);
  requestAnimationFrame(loop);
}

/* ====== 初始化 ====== */
function init(){
  const svg=document.getElementById('svg');
  const{demoG}=build(svg);
  buildDynamic(svg,demoG);

  // 交互控件
  const freqSlider=document.getElementById('freqSlider');
  const pressSlider=document.getElementById('pressSlider');
  const freqValEl=document.getElementById('freqVal');
  const pressValEl=document.getElementById('pressVal');
  freqSlider.addEventListener('input',()=>{
    freq=parseFloat(freqSlider.value);
    freqValEl.textContent=freq.toFixed(2);
  });
  pressSlider.addEventListener('input',()=>{
    press=parseFloat(pressSlider.value);
    pressValEl.textContent=press.toFixed(2);
  });

  requestAnimationFrame(loop);
}

document.addEventListener('DOMContentLoaded',init);
</script>
</body>
</html>

实现说明

本动画基于 TRIZ "最终理想解" 思想,直接展示柔性壁面亥姆霍兹共振器消除低频脉动的理想工作状态,核心设计如下:

IFR 聚焦

  • 不做"问题→解决"对比,动画一启动就展示系统完美运作:脉动波逐级衰减直至近零,视觉上用红→橙→青→绿四色波形与振幅递减直观呈现消声过程
  • 右下角反相叠加原理小窗,实时展示"原脉动 + 反相 = 抵消"的三行对比波形

核心创新高亮

  • 柔性壁面采用琥珀色渐变 + feGaussianBlur 发光滤镜,与冷色调管道形成强烈视觉反差,标注"0.3mm · 自适应调谐"
  • 壁面波纹随压力/频率实时膨胀收缩,直观展示自适应调谐破除固定频率局限

资源巧妙利用

  • 短颈粒子振荡 + 腔体反相波 + 热能耗散指示三位一体,展示"声抗抵消→能量耗散→壁面调谐"的协同过程
  • 气流粒子贯穿主管道,呼应"不增加流阻"的设计约束

交互控制

  • 脉动频率滑块改变波速和共振响应频率
  • 内部压力滑块控制柔性壁面变形幅度和能量耗散强度
积分规则:第一轮对话扣减8分,后续每轮扣6分