独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>卡门涡街与声波干涉抵消原理</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<style>
:root {
--bg-color: #050914;
--grid-color: rgba(255, 255, 255, 0.03);
--text-main: #E2E8F0;
--text-dim: #64748B;
--cyan-glow: rgba(0, 240, 255, 0.6);
--magenta-glow: rgba(255, 0, 85, 0.6);
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: var(--bg-color);
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 20px 20px;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
overflow: hidden;
color: var(--text-main);
}
/* 保证 SVG 能够居中展示且比例正确 */
.svg-container {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
svg {
width: 100%;
height: 100%;
max-width: 1200px;
max-height: 800px;
}
/* 涡流和气流的特定动画样式 */
.airflow-line {
stroke-dasharray: 200;
stroke-dashoffset: 200;
}
.wave-path {
stroke-dasharray: 400;
stroke-dashoffset: 400;
}
.info-panel {
background: rgba(10, 15, 25, 0.7);
backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
</style>
</head>
<body>
<!-- 边缘说明面板,严格控制字号和位置,不遮挡中央 -->
<div class="absolute top-6 left-6 info-panel p-4 rounded-lg max-w-xs z-10 pointer-events-none">
<h1 class="text-sm font-bold text-cyan-400 mb-2 uppercase tracking-widest">声波干涉降噪微观模型</h1>
<p class="text-xs text-gray-400 leading-relaxed mb-2">
利用 IFR (理想最终解) 思想,改造现有资源解决声学矛盾。
将平直出风口改造为 <strong>V型锯齿状边缘</strong>,强制分割流体。
</p>
<div class="flex flex-col gap-1 mt-3 border-t border-gray-700 pt-2 text-[11px] text-gray-500">
<span class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-cyan-400 opacity-80"></span> 高速主流气流
</span>
<span class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-pink-500 opacity-80"></span> 波峰/波谷相位差涡流
</span>
<span class="flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-green-400 opacity-80"></span> 物理干涉抵消区
</span>
</div>
</div>
<div class="absolute bottom-6 right-6 info-panel p-3 rounded-lg z-10 pointer-events-none text-right">
<p class="text-[10px] text-gray-500 uppercase tracking-widest mb-1">设计参数</p>
<p class="text-xs text-gray-300 font-mono">锯齿深度: 2.5mm <br> 相邻夹角: 60°</p>
</div>
<!-- 主体 SVG 动画区 -->
<div class="svg-container">
<svg viewBox="0 0 1200 700" preserveAspectRatio="xMidYMid meet">
<!-- 滤镜定义 -->
<defs>
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-magenta" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-green" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="shadow" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="5" dy="5" stdDeviation="6" flood-color="#000" flood-opacity="0.8"/>
</filter>
<linearGradient id="nozzle-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1E293B" />
<stop offset="80%" stop-color="#334155" />
<stop offset="100%" stop-color="#0F172A" />
</linearGradient>
<linearGradient id="airflow-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="transparent" />
<stop offset="20%" stop-color="#00F0FF" />
<stop offset="80%" stop-color="#00F0FF" />
<stop offset="100%" stop-color="transparent" />
</linearGradient>
<!-- 涡流图层复用 -->
<g id="vortex-symbol">
<path d="M 0,0
C 10,-10 20,-5 20,5
C 20,15 5,20 -5,15
C -15,10 -15,-5 -5,-15
C 5,-25 20,-20 25,-5"
fill="none" stroke-width="1.5" stroke-linecap="round"/>
</g>
</defs>
<!-- ===================== 结构层 ===================== -->
<g id="nozzle-structure" filter="url(#shadow)">
<!-- 风嘴主体 -->
<!-- 平直风嘴改为波浪形锯齿,从 x=300 开始起伏 -->
<path d="
M 50,150
L 350,150
L 380,180 L 350,210
L 380,240 L 350,270
L 380,300 L 350,330
L 380,360 L 350,390
L 380,420 L 350,450
L 50,450 Z"
fill="url(#nozzle-grad)" stroke="#475569" stroke-width="2"/>
<!-- 内部深色通道细节 -->
<path d="M 50,165 L 340,165" stroke="#0F172A" stroke-width="4" opacity="0.5"/>
<path d="M 50,435 L 340,435" stroke="#0F172A" stroke-width="4" opacity="0.5"/>
<!-- 重点高亮锯齿边缘 -->
<path id="serrated-edge" d="
M 350,150
L 380,180 L 350,210
L 380,240 L 350,270
L 380,300 L 350,330
L 380,360 L 350,390
L 380,420 L 350,450"
fill="none" stroke="#00F0FF" stroke-width="3" filter="url(#glow-cyan)" opacity="0.8"/>
</g>
<!-- 结构参数标注 -->
<g id="dimensions" opacity="0" class="text-[10px] fill-gray-400 font-mono">
<!-- 夹角 -->
<path d="M 365,195 Q 375,195 370,200" fill="none" stroke="#64748B" stroke-width="1" stroke-dasharray="2,2"/>
<text x="385" y="198" fill="#94A3B8">60°</text>
<!-- 深度 -->
<line x1="350" y1="130" x2="380" y2="130" stroke="#64748B" stroke-width="1"/>
<line x1="350" y1="125" x2="350" y2="135" stroke="#64748B" stroke-width="1"/>
<line x1="380" y1="125" x2="380" y2="135" stroke="#64748B" stroke-width="1"/>
<text x="352" y="120" fill="#94A3B8">2.5mm</text>
</g>
<!-- ===================== 流场层 (气流和涡流) ===================== -->
<!-- 内部高速直线气流 -->
<g id="internal-airflow">
<!-- 由 JS 动态生成线条 -->
</g>
<!-- 外部被打散的干涉气流区 -->
<g id="external-airflow" filter="url(#glow-cyan)">
<!-- 由 JS 动态生成 -->
</g>
<!-- 相位差涡流发生点 (波峰波谷交错) -->
<g id="vortices" filter="url(#glow-magenta)">
<!-- 由 JS 生成带有位移和旋转的涡流 -->
</g>
<!-- ===================== 微观物理干涉原理放大视图 ===================== -->
<!-- 连接线 -->
<path id="micro-link" d="M 400,300 Q 550,300 700,200 L 760,200" fill="none" stroke="#475569" stroke-width="1.5" stroke-dasharray="4,4" opacity="0"/>
<g id="micro-view" transform="translate(850, 200)" opacity="0">
<!-- HUD 外框 -->
<circle cx="0" cy="0" r="120" fill="none" stroke="#334155" stroke-width="2"/>
<circle cx="0" cy="0" r="130" fill="none" stroke="#1E293B" stroke-width="1" stroke-dasharray="10, 5"/>
<circle cx="0" cy="0" r="120" fill="#0A0F1C" opacity="0.9"/>
<text x="0" y="-140" text-anchor="middle" class="text-[12px] fill-cyan-400 tracking-widest">物理干涉原理</text>
<!-- 坐标轴 -->
<line x1="-100" y1="0" x2="100" y2="0" stroke="#1E293B" stroke-width="1"/>
<line x1="0" y1="-80" x2="0" y2="80" stroke="#1E293B" stroke-width="1"/>
<!-- 声波 1 (波峰产生的声波,相位0) -->
<path id="wave1" d="M -90,0 Q -67.5,-60 -45,0 T 0,0 T 45,0 T 90,0" fill="none" stroke="#FF0055" stroke-width="2" filter="url(#glow-magenta)"/>
<!-- 声波 2 (波谷产生的声波,相位180) -->
<path id="wave2" d="M -90,0 Q -67.5,60 -45,0 T 0,0 T 45,0 T 90,0" fill="none" stroke="#0077FF" stroke-width="2" filter="url(#glow-cyan)"/>
<!-- 干涉后的抵消结果波 (起初隐藏,干涉后显示) -->
<path id="wave-result" d="M -90,0 Q -67.5,-5 -45,0 T 0,0 T 45,0 T 90,0" fill="none" stroke="#00FF88" stroke-width="3" filter="url(#glow-green)" opacity="0"/>
<!-- 注释标签 -->
<text x="-70" y="70" class="text-[9px] fill-[#FF0055]">波峰涡流声波</text>
<text x="-70" y="-60" class="text-[9px] fill-[#0077FF]">波谷涡流声波</text>
<text id="cancel-text" x="30" y="-20" class="text-[10px] fill-[#00FF88] font-bold" opacity="0">反相抵消</text>
</g>
<!-- ===================== 输出低噪平稳气流 ===================== -->
<g id="smooth-output" opacity="0">
<path d="M 450,200 Q 800,200 1100,200" fill="none" stroke="url(#airflow-grad)" stroke-width="4" filter="url(#glow-green)" opacity="0.3"/>
<path d="M 450,300 Q 800,300 1100,300" fill="none" stroke="url(#airflow-grad)" stroke-width="4" filter="url(#glow-green)" opacity="0.3"/>
<path d="M 450,400 Q 800,400 1100,400" fill="none" stroke="url(#airflow-grad)" stroke-width="4" filter="url(#glow-green)" opacity="0.3"/>
<text x="1050" y="300" class="text-[14px] fill-green-400 tracking-wider font-bold" filter="url(#glow-green)">高速低噪输出</text>
</g>
</svg>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
gsap.registerPlugin();
// 1. 生成内部加速气流线
const internalGroup = document.getElementById('internal-airflow');
for(let i=0; i<12; i++) {
const y = 160 + i * 25;
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute("x1", "50");
line.setAttribute("y1", y);
line.setAttribute("x2", "340");
line.setAttribute("y2", y);
line.setAttribute("stroke", "url(#airflow-grad)");
line.setAttribute("stroke-width", i % 3 === 0 ? "3" : "1.5");
line.setAttribute("class", "airflow-line");
line.setAttribute("opacity", "0.6");
internalGroup.appendChild(line);
// 给这些线条添加连续流动的动画
gsap.to(line, {
strokeDashoffset: 0,
duration: 1 + Math.random() * 0.5,
repeat: -1,
ease: "none",
delay: Math.random()
});
}
// 2. 生成外部打散的涡流和波浪气流
const externalGroup = document.getElementById('external-airflow');
const vortexGroup = document.getElementById('vortices');
// 记录波峰(380)和波谷(350)的 Y 坐标
const peaks = [180, 240, 300, 360, 420];
const valleys = [150, 210, 270, 330, 390, 450];
// 外部混乱的短波浪线
for(let i=0; i<20; i++) {
const startY = 160 + i * 15;
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
// 画一条微波浪线
const d = `M 380,${startY} Q 420,${startY-10} 460,${startY} T 540,${startY} T 620,${startY}`;
path.setAttribute("d", d);
path.setAttribute("fill", "none");
path.setAttribute("stroke", "#00F0FF");
path.setAttribute("stroke-width", "1");
path.setAttribute("opacity", "0.3");
path.setAttribute("stroke-dasharray", "50");
path.setAttribute("stroke-dashoffset", "50");
externalGroup.appendChild(path);
gsap.to(path, {
strokeDashoffset: -50,
duration: 1.5 + Math.random(),
repeat: -1,
ease: "none",
delay: Math.random()
});
}
// 在波峰和波谷生成持续产生的涡流 (体现三维切割和相位差)
function createVortex(x, y, color) {
const use = document.createElementNS("http://www.w3.org/2000/svg", "use");
use.setAttribute("href", "#vortex-symbol");
use.setAttribute("x", x);
use.setAttribute("y", y);
use.setAttribute("stroke", color);
vortexGroup.appendChild(use);
return use;
}
// 生成涡流持续动画
function startVortexEmitters() {
peaks.forEach(py => {
setInterval(() => {
const v = createVortex(380, py, "#FF0055"); // 波峰红涡流
gsap.fromTo(v,
{ x: 380, scale: 0.1, rotation: 0, opacity: 0.8 },
{ x: 480, y: py + (Math.random()*20-10), scale: 1.5, rotation: 360, opacity: 0, duration: 1.5, ease: "power1.out", onComplete: () => v.remove() }
);
}, 800 + Math.random() * 400);
});
valleys.forEach(vy => {
setInterval(() => {
const v = createVortex(350, vy, "#0077FF"); // 波谷蓝涡流
gsap.fromTo(v,
{ x: 350, scale: 0.1, rotation: 0, opacity: 0.8 },
{ x: 480, y: vy + (Math.random()*20-10), scale: 1.2, rotation: -360, opacity: 0, duration: 1.8, ease: "power1.out", onComplete: () => v.remove() }
);
}, 800 + Math.random() * 400);
});
}
// ================= 主线叙事 Timeline (讲解原理,循环播放) =================
const masterTl = gsap.timeline({ repeat: -1, repeatDelay: 2 });
// 阶段 1: 展示系统与关键结构特征
masterTl.fromTo("#nozzle-structure", {x: -30, opacity: 0}, {x: 0, opacity: 1, duration: 1.5, ease: "power2.out"})
.to("#dimensions", {opacity: 1, duration: 0.8})
.to("#serrated-edge", {opacity: 1, filter: "brightness(2)", duration: 0.5, yoyo: true, repeat: 3}, "-=0.5")
.add(() => { if(masterTl.iteration() === 1) startVortexEmitters(); }); // 启动连续流场
// 阶段 2: 引导视线到微观原理区
masterTl.to("#micro-link", {opacity: 0.6, strokeDashoffset: 0, duration: 0.8, ease: "power1.inOut"})
.fromTo("#micro-view", {scale: 0.8, opacity: 0}, {scale: 1, opacity: 1, duration: 1, ease: "back.out(1.5)"});
// 阶段 3: 微观声波演示干涉原理
// 两个原本振幅极大、相位相反的声波,随着距离推移向中间靠拢并合并
// 利用 scaleY 来模拟波的振幅降低抵消过程
const waveTime = 2.5;
masterTl.to("#wave1", {scaleY: 0.1, opacity: 0, duration: waveTime, ease: "power2.inOut", transformOrigin: "center center"}, "+=0.5")
.to("#wave2", {scaleY: 0.1, opacity: 0, duration: waveTime, ease: "power2.inOut", transformOrigin: "center center"}, `<`)
.to("#wave-result", {opacity: 1, duration: 0.5}, `-=${waveTime/2}`)
.to("#cancel-text", {opacity: 1, scale: 1.2, duration: 0.5, yoyo: true, repeat: 1}, `-=${waveTime/3}`);
// 阶段 4: 宏观结果呈现 (输出平稳低噪气流)
masterTl.to("#smooth-output", {opacity: 1, duration: 1.5, ease: "power1.inOut"}, "-=1")
// 在最终状态保持几秒
.to({}, {duration: 3})
// 渐隐微观视图,准备下一次循环
.to("#micro-view, #micro-link, #smooth-output", {opacity: 0, duration: 1});
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
