独立渲染引擎就绪引擎就绪
<!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分
等待动画代码生成...
