分享图
动画工坊
引擎就绪
<!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分