分享图
A
动画渲染工坊
就绪
<!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=Orbitron:wght@400;700;900&family=Noto+Sans+SC:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
  :root {
    --bg: #060a14;
    --flame-hot: #ff3d00;
    --flame-warm: #ff8f00;
    --ceramic-glow: #e65100;
    --ir-cyan: #00e5ff;
    --ir-teal: #00bcd4;
    --water-blue: #42a5f5;
    --water-deep: #1565c0;
    --reflector-silver: #b0bec5;
    --accent-green: #76ff03;
    --text: #eceff1;
    --text-dim: #607d8b;
    --panel-bg: rgba(10, 18, 32, 0.92);
  }
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body {
    background: var(--bg);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    font-family: 'Noto Sans SC', sans-serif;
    color: var(--text);
    overflow-x: hidden;
    padding: 12px;
  }
  .container {
    width: 100%;
    max-width: 1100px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
  }
  .title-bar {
    text-align: center;
    margin-bottom: 4px;
  }
  .title-bar h1 {
    font-family: 'Orbitron', sans-serif;
    font-size: clamp(16px, 2.4vw, 26px);
    font-weight: 700;
    letter-spacing: 2px;
    color: var(--ir-cyan);
    text-shadow: 0 0 20px rgba(0,229,255,0.35);
  }
  .title-bar p {
    font-size: clamp(11px, 1.3vw, 14px);
    color: var(--text-dim);
    margin-top: 4px;
    font-weight: 300;
  }
  .svg-wrap {
    width: 100%;
    border: 1px solid rgba(0,229,255,0.12);
    border-radius: 12px;
    overflow: hidden;
    background: linear-gradient(180deg, #080e1c 0%, #0a1222 100%);
    box-shadow: 0 0 60px rgba(0,229,255,0.06), inset 0 0 80px rgba(0,0,0,0.3);
  }
  #mainSvg { display: block; width: 100%; height: auto; }

  .controls {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 20px;
    padding: 14px 24px;
    background: var(--panel-bg);
    border: 1px solid rgba(0,229,255,0.1);
    border-radius: 10px;
  }
  .ctrl-group {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .ctrl-group label {
    font-size: 13px;
    color: var(--text-dim);
    white-space: nowrap;
  }
  .ctrl-group .val {
    font-family: 'Orbitron', sans-serif;
    font-size: 15px;
    font-weight: 700;
    min-width: 68px;
    text-align: right;
  }
  input[type=range] {
    -webkit-appearance: none;
    appearance: none;
    width: 180px;
    height: 6px;
    border-radius: 3px;
    background: linear-gradient(90deg, #ff6f00 0%, var(--ir-cyan) 60%, var(--accent-green) 100%);
    outline: none;
    cursor: pointer;
  }
  input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 18px; height: 18px;
    border-radius: 50%;
    background: var(--text);
    border: 2px solid var(--ir-cyan);
    box-shadow: 0 0 8px rgba(0,229,255,0.5);
  }
  .phase-indicator {
    display: flex;
    gap: 6px;
    align-items: center;
  }
  .phase-dot {
    width: 10px; height: 10px;
    border-radius: 50%;
    background: var(--text-dim);
    transition: all 0.4s;
  }
  .phase-dot.active {
    background: var(--ir-cyan);
    box-shadow: 0 0 10px var(--ir-cyan);
    transform: scale(1.3);
  }
  .phase-label {
    font-size: 11px;
    color: var(--text-dim);
    max-width: 56px;
    text-align: center;
    line-height: 1.2;
  }
  .phase-step { display: flex; flex-direction: column; align-items: center; gap: 3px; }
  .match-badge {
    font-family: 'Orbitron', sans-serif;
    font-size: 12px;
    padding: 4px 12px;
    border-radius: 20px;
    font-weight: 700;
    transition: all 0.5s;
  }
  .match-badge.optimal {
    background: rgba(118,255,3,0.15);
    color: var(--accent-green);
    border: 1px solid var(--accent-green);
    box-shadow: 0 0 12px rgba(118,255,3,0.3);
  }
  .match-badge.mismatch {
    background: rgba(255,61,0,0.12);
    color: var(--flame-hot);
    border: 1px solid rgba(255,61,0,0.4);
  }

  /* SVG 内部动画 */
  @keyframes flameFlicker {
    0%, 100% { opacity: 0.85; transform: scaleY(1) translateY(0); }
    25% { opacity: 1; transform: scaleY(1.08) translateY(-2px); }
    50% { opacity: 0.75; transform: scaleY(0.94) translateY(1px); }
    75% { opacity: 0.95; transform: scaleY(1.04) translateY(-1px); }
  }
  @keyframes glowPulse {
    0%, 100% { opacity: 0.6; }
    50% { opacity: 1; }
  }
  @keyframes moleculeVibrate {
    0%, 100% { transform: translate(var(--mx), var(--my)) rotate(0deg); }
    25% { transform: translate(calc(var(--mx) + var(--vx)), calc(var(--my) - var(--vy))) rotate(3deg); }
    75% { transform: translate(calc(var(--mx) - var(--vx)), calc(var(--my) + var(--vy))) rotate(-3deg); }
  }
  @keyframes waveDash {
    to { stroke-dashoffset: -40; }
  }
  @keyframes radExpand {
    0% { r: 0; opacity: 0.7; }
    100% { r: 60; opacity: 0; }
  }
  @keyframes particleFlow {
    0% { offset-distance: 0%; opacity: 0; }
    10% { opacity: 1; }
    90% { opacity: 1; }
    100% { offset-distance: 100%; opacity: 0; }
  }
</style>
</head>
<body>
<div class="container">
  <div class="title-bar">
    <h1>FAR-IR RADIATION FOCUSING PRINCIPLE</h1>
    <p>梯度发射率多孔陶瓷火盖 + 微晶抛物面聚能盘 — 维恩位移定律驱动的光谱匹配传热</p>
  </div>

  <div class="svg-wrap">
    <svg id="mainSvg" viewBox="0 0 1200 880" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- 渐变定义 -->
        <radialGradient id="bgGlow" cx="50%" cy="55%" r="55%">
          <stop offset="0%" stop-color="#0d1a30" />
          <stop offset="100%" stop-color="#060a14" />
        </radialGradient>
        <linearGradient id="flameGrad" x1="0" y1="1" x2="0" y2="0">
          <stop offset="0%" stop-color="#ff6f00" />
          <stop offset="40%" stop-color="#ff3d00" />
          <stop offset="80%" stop-color="#ffab00" stop-opacity="0.7" />
          <stop offset="100%" stop-color="#fff176" stop-opacity="0.3" />
        </linearGradient>
        <linearGradient id="ceramicGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#a1887f" />
          <stop offset="50%" stop-color="#8d6e63" />
          <stop offset="100%" stop-color="#6d4c41" />
        </linearGradient>
        <linearGradient id="coatingGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#ff8f00" />
          <stop offset="100%" stop-color="#e65100" />
        </linearGradient>
        <linearGradient id="reflectorGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#cfd8dc" />
          <stop offset="30%" stop-color="#90a4ae" />
          <stop offset="70%" stop-color="#b0bec5" />
          <stop offset="100%" stop-color="#78909c" />
        </linearGradient>
        <linearGradient id="potGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="#546e7a" />
          <stop offset="100%" stop-color="#37474f" />
        </linearGradient>
        <linearGradient id="waterGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="rgba(66,165,245,0.12)" />
          <stop offset="100%" stop-color="rgba(21,101,192,0.25)" />
        </linearGradient>

        <!-- 滤镜 -->
        <filter id="glowCyan" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur" />
          <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="glowOrange" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="6" result="blur" />
          <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="glowStrong" x="-80%" y="-80%" width="260%" height="260%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
          <feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>
        <filter id="softGlow" x="-30%" y="-30%" width="160%" height="160%">
          <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur" />
          <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
        </filter>

        <!-- 多孔陶瓷纹理 -->
        <pattern id="porePattern" x="0" y="0" width="14" height="14" patternUnits="userSpaceOnUse">
          <circle cx="4" cy="4" r="1.8" fill="#4e342e" opacity="0.5"/>
          <circle cx="11" cy="10" r="1.5" fill="#4e342e" opacity="0.4"/>
          <circle cx="8" cy="2" r="1" fill="#3e2723" opacity="0.3"/>
        </pattern>
        <!-- 锅底微孔纹理 -->
        <pattern id="microPorePattern" x="0" y="0" width="8" height="8" patternUnits="userSpaceOnUse">
          <circle cx="2" cy="2" r="0.8" fill="#263238" opacity="0.6"/>
          <circle cx="6" cy="6" r="0.6" fill="#263238" opacity="0.5"/>
        </pattern>
        <!-- 网格背景 -->
        <pattern id="gridPattern" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse">
          <path d="M 40 0 L 0 0 0 40" fill="none" stroke="rgba(0,229,255,0.04)" stroke-width="0.5"/>
        </pattern>

        <!-- 光线运动路径 -->
        <path id="rayDirect1" d="M 560,505 L 560,240" fill="none"/>
        <path id="rayDirect2" d="M 600,505 L 600,240" fill="none"/>
        <path id="rayDirect3" d="M 640,505 L 640,240" fill="none"/>
        <path id="rayReflectL1" d="M 510,540 Q 300,470 460,240" fill="none"/>
        <path id="rayReflectL2" d="M 500,580 Q 240,530 400,240" fill="none"/>
        <path id="rayReflectR1" d="M 690,540 Q 900,470 740,240" fill="none"/>
        <path id="rayReflectR2" d="M 700,580 Q 960,530 800,240" fill="none"/>
      </defs>

      <!-- 背景 -->
      <rect width="1200" height="880" fill="url(#bgGlow)"/>
      <rect width="1200" height="880" fill="url(#gridPattern)"/>

      <!-- ====== 聚能盘 (抛物面反射器) ====== -->
      <g id="reflectorGroup">
        <!-- 抛物面外壳 -->
        <path d="M 230,430 C 290,630 440,720 600,738 C 760,720 910,630 970,430"
              fill="none" stroke="url(#reflectorGrad)" stroke-width="28" stroke-linecap="round"
              opacity="0.85"/>
        <!-- 内反射面高光 -->
        <path d="M 245,435 C 300,620 445,710 600,726 C 755,710 900,620 955,435"
              fill="none" stroke="rgba(255,255,255,0.12)" stroke-width="4" stroke-linecap="round"/>
        <!-- 标注线 -->
        <line x1="970" y1="430" x2="1030" y2="380" stroke="rgba(176,190,197,0.4)" stroke-width="1" stroke-dasharray="4,3"/>
        <text x="1035" y="378" fill="#90a4ae" font-size="12" font-family="'Noto Sans SC'" font-weight="400">微晶抛物面聚能盘</text>
        <text x="1035" y="395" fill="#607d8b" font-size="10" font-family="'Noto Sans SC'" font-weight="300">焦距对准锅底中心</text>
      </g>

      <!-- ====== 多孔陶瓷火盖 ====== -->
      <g id="burnerGroup">
        <!-- 陶瓷主体 -->
        <rect x="498" y="530" width="204" height="130" rx="10" fill="url(#ceramicGrad)" stroke="#5d4037" stroke-width="1.5"/>
        <!-- 多孔纹理叠加 -->
        <rect x="498" y="530" width="204" height="130" rx="10" fill="url(#porePattern)"/>
        <!-- 远红外涂层 (顶部内表面) -->
        <rect x="503" y="530" width="194" height="12" rx="4" fill="url(#coatingGrad)" opacity="0.9"/>
        <rect x="503" y="530" width="194" height="12" rx="4" fill="none" stroke="#ff6f00" stroke-width="0.5" opacity="0.6"/>

        <!-- 内部火焰 -->
        <g id="flameGroup" style="animation: flameFlicker 0.8s ease-in-out infinite; transform-origin: 600px 600px;">
          <ellipse cx="600" cy="600" rx="50" ry="40" fill="url(#flameGrad)" filter="url(#glowOrange)" opacity="0.85"/>
          <ellipse cx="600" cy="590" rx="30" ry="28" fill="#ffcc02" opacity="0.5"/>
          <ellipse cx="600" cy="585" rx="15" ry="18" fill="#fff9c4" opacity="0.4"/>
        </g>

        <!-- 陶瓷表面热辐射光晕 -->
        <ellipse cx="600" cy="530" rx="90" ry="8" fill="#ff8f00" opacity="0.25" filter="url(#glowOrange)">
          <animate attributeName="opacity" values="0.15;0.35;0.15" dur="2s" repeatCount="indefinite"/>
        </ellipse>

        <!-- 标注 -->
        <line x1="498" y1="595" x2="420" y2="620" stroke="rgba(255,143,0,0.4)" stroke-width="1" stroke-dasharray="4,3"/>
        <text x="280" y="618" fill="#ffab00" font-size="12" font-family="'Noto Sans SC'" font-weight="600">碳化硅基多孔陶瓷火盖</text>
        <text x="280" y="636" fill="#ff8f00" font-size="10" font-family="'Noto Sans SC'" font-weight="300">850~950°C · 发射率 &gt; 0.9</text>
        <text x="280" y="654" fill="#ff6f00" font-size="10" font-family="'Noto Sans SC'" font-weight="300">过渡金属氧化物远红外涂层</text>

        <!-- 温度标注 -->
        <g id="tempLabel" transform="translate(720, 580)">
          <rect x="0" y="-12" width="90" height="24" rx="4" fill="rgba(255,143,0,0.12)" stroke="rgba(255,143,0,0.3)" stroke-width="0.8"/>
          <text x="45" y="4" text-anchor="middle" fill="#ffab00" font-size="12" font-family="'Orbitron'" font-weight="700" id="tempDisplay">900°C</text>
        </g>
      </g>

      <!-- ====== 辐射射线 (JS 动态绘制) ====== -->
      <g id="radiationGroup"></g>

      <!-- ====== 辐射波纹 (从陶瓷表面扩散) ====== -->
      <g id="waveGroup"></g>

      <!-- ====== 锅具截面 ====== -->
      <g id="potGroup">
        <!-- 锅内水/食材 -->
        <rect x="366" y="85" width="468" height="155" rx="3" fill="url(#waterGrad)"/>

        <!-- 锅壁 -->
        <path d="M 360,80 L 360,238 Q 360,248 370,248 L 830,248 Q 840,248 840,238 L 840,80"
              fill="none" stroke="#546e7a" stroke-width="8" stroke-linejoin="round"/>
        <!-- 锅底 -->
        <rect x="360" y="234" width="480" height="20" rx="2" fill="url(#potGrad)"/>
        <!-- 锅底微孔层 -->
        <rect x="360" y="240" width="480" height="14" rx="1" fill="url(#microPorePattern)" opacity="0.7"/>
        <!-- 选择性吸收涂层 -->
        <rect x="365" y="236" width="470" height="4" rx="1" fill="#455a64" opacity="0.6"/>
        <line x1="365" y1="238" x2="835" y2="238" stroke="#607d8b" stroke-width="0.5" stroke-dasharray="2,2" opacity="0.4"/>

        <!-- 标注 -->
        <line x1="840" y1="242" x2="920" y2="268" stroke="rgba(84,110,122,0.4)" stroke-width="1" stroke-dasharray="4,3"/>
        <text x="925" y="265" fill="#78909c" font-size="11" font-family="'Noto Sans SC'" font-weight="400">亚微米级微孔结构锅底</text>
        <text x="925" y="282" fill="#607d8b" font-size="10" font-family="'Noto Sans SC'" font-weight="300">选择性吸收 · 红外穿透</text>
      </g>

      <!-- ====== 水分子群 ====== -->
      <g id="moleculeGroup"></g>

      <!-- ====== 光谱匹配指示器 ====== -->
      <g id="spectralDisplay" transform="translate(30, 680)">
        <rect x="0" y="0" width="320" height="160" rx="8" fill="rgba(6,10,20,0.85)" stroke="rgba(0,229,255,0.15)" stroke-width="1"/>
        <text x="160" y="22" text-anchor="middle" fill="#90a4ae" font-size="11" font-family="'Noto Sans SC'" font-weight="600">光谱匹配度 · 维恩位移定律</text>
        <text x="160" y="38" text-anchor="middle" fill="#607d8b" font-size="9" font-family="'Orbitron'">λmax = 2898 / T(K) μm</text>

        <!-- 波长轴 -->
        <line x1="30" y1="120" x2="290" y2="120" stroke="#455a64" stroke-width="1"/>
        <text x="30" y="135" fill="#607d8b" font-size="9" font-family="'Orbitron'">2μm</text>
        <text x="140" y="135" fill="#607d8b" font-size="9" font-family="'Orbitron'">3μm</text>
        <text x="260" y="135" fill="#607d8b" font-size="9" font-family="'Orbitron'">5μm</text>

        <!-- 水吸收带 (2.7-3.2μm) -->
        <rect id="waterAbsBand" x="108" y="55" width="42" height="60" rx="2" fill="rgba(66,165,245,0.12)" stroke="rgba(66,165,245,0.3)" stroke-width="0.8"/>
        <text x="129" y="52" text-anchor="middle" fill="#42a5f5" font-size="8" font-family="'Noto Sans SC'">H₂O吸收带</text>

        <!-- 发射峰 (动态) -->
        <g id="emissionPeak">
          <line id="emissionLine" x1="129" y1="60" x2="129" y2="118" stroke="#ff8f00" stroke-width="2" opacity="0.8"/>
          <polygon id="emissionArrow" points="129,58 124,68 134,68" fill="#ff8f00" opacity="0.9"/>
        </g>
        <text id="wavelengthLabel" x="129" y="150" text-anchor="middle" fill="#ffab00" font-size="10" font-family="'Orbitron'" font-weight="700">2.47μm</text>

        <!-- 匹配度指示 -->
        <text id="matchText" x="250" y="95" text-anchor="middle" fill="#76ff03" font-size="13" font-family="'Orbitron'" font-weight="700">MATCH</text>
      </g>

      <!-- ====== 核心机理文字标注 ====== -->
      <g id="mechanismLabels">
        <!-- 步骤1 -->
        <g transform="translate(40, 450)">
          <circle cx="8" cy="0" r="8" fill="none" stroke="#ff8f00" stroke-width="1.5" opacity="0.7"/>
          <text x="8" y="4" text-anchor="middle" fill="#ff8f00" font-size="9" font-family="'Orbitron'" font-weight="700">1</text>
          <text x="22" y="4" fill="#ffab00" font-size="11" font-family="'Noto Sans SC'" font-weight="600">多孔陶瓷蓄热</text>
          <text x="22" y="18" fill="#8d6e63" font-size="9" font-family="'Noto Sans SC'" font-weight="300">1200°C明火 → 900°C辐射体</text>
        </g>
        <!-- 步骤2 -->
        <g transform="translate(40, 490)">
          <circle cx="8" cy="0" r="8" fill="none" stroke="#00e5ff" stroke-width="1.5" opacity="0.7"/>
          <text x="8" y="4" text-anchor="middle" fill="#00e5ff" font-size="9" font-family="'Orbitron'" font-weight="700">2</text>
          <text x="22" y="4" fill="#00e5ff" font-size="11" font-family="'Noto Sans SC'" font-weight="600">远红外涂层辐射</text>
          <text x="22" y="18" fill="#0097a7" font-size="9" font-family="'Noto Sans SC'" font-weight="300">发射率&gt;0.9 · 峰值2.9μm</text>
        </g>
        <!-- 步骤3 -->
        <g transform="translate(40, 530)">
          <circle cx="8" cy="0" r="8" fill="none" stroke="#b0bec5" stroke-width="1.5" opacity="0.7"/>
          <text x="8" y="4" text-anchor="middle" fill="#b0bec5" font-size="9" font-family="'Orbitron'" font-weight="700">3</text>
          <text x="22" y="4" fill="#b0bec5" font-size="11" font-family="'Noto Sans SC'" font-weight="600">抛物面聚焦</text>
          <text x="22" y="18" fill="#78909c" font-size="9" font-family="'Noto Sans SC'" font-weight="300">散射红外 → 锅底中心</text>
        </g>
        <!-- 步骤4 -->
        <g transform="translate(40, 570)">
          <circle cx="8" cy="0" r="8" fill="none" stroke="#42a5f5" stroke-width="1.5" opacity="0.7"/>
          <text x="8" y="4" text-anchor="middle" fill="#42a5f5" font-size="9" font-family="'Orbitron'" font-weight="700">4</text>
          <text x="22" y="4" fill="#42a5f5" font-size="11" font-family="'Noto Sans SC'" font-weight="600">水分子共振吸收</text>
          <text x="22" y="18" fill="#1e88e5" font-size="9" font-family="'Noto Sans SC'" font-weight="300">2.9μm = O-H伸缩峰 · 直接产热</text>
        </g>
      </g>

      <!-- ====== IFR 理想解标识 ====== -->
      <g transform="translate(940, 700)">
        <rect x="0" y="0" width="220" height="130" rx="8" fill="rgba(6,10,20,0.85)" stroke="rgba(118,255,3,0.2)" stroke-width="1"/>
        <text x="110" y="22" text-anchor="middle" fill="#76ff03" font-size="11" font-family="'Orbitron'" font-weight="700" letter-spacing="1">IDEAL FINAL RESULT</text>
        <line x1="15" y1="30" x2="205" y2="30" stroke="rgba(118,255,3,0.15)" stroke-width="0.5"/>
        <text x="15" y="48" fill="#aed581" font-size="10" font-family="'Noto Sans SC'" font-weight="400">▸ 热源-辐射-吸收 频率绝对协调</text>
        <text x="15" y="66" fill="#aed581" font-size="10" font-family="'Noto Sans SC'" font-weight="400">▸ 光谱匹配替代温度堆砌</text>
        <text x="15" y="84" fill="#aed581" font-size="10" font-family="'Noto Sans SC'" font-weight="400">▸ 陶瓷自身 = 波长变换器</text>
        <text x="15" y="102" fill="#aed581" font-size="10" font-family="'Noto Sans SC'" font-weight="400">▸ 反射盘 = 零能耗聚能器</text>
        <text x="15" y="120" fill="#81c784" font-size="9" font-family="'Noto Sans SC'" font-weight="300">不增加复杂度,矛盾自行消失</text>
      </g>

    </svg>
  </div>

  <!-- 控制面板 -->
  <div class="controls">
    <div class="ctrl-group">
      <label>陶瓷温度</label>
      <input type="range" id="tempSlider" min="700" max="1200" value="900" step="10"/>
      <span class="val" id="tempVal" style="color: var(--flame-warm);">900°C</span>
    </div>
    <div class="ctrl-group">
      <label>峰值波长</label>
      <span class="val" id="waveVal" style="color: var(--ir-cyan);">2.58μm</span>
    </div>
    <div class="ctrl-group">
      <label>匹配状态</label>
      <span class="match-badge optimal" id="matchBadge">光谱匹配</span>
    </div>
    <div class="phase-indicator">
      <div class="phase-step"><div class="phase-dot active" id="pd0"></div><span class="phase-label">蓄热</span></div>
      <div class="phase-step"><div class="phase-dot" id="pd1"></div><span class="phase-label">辐射</span></div>
      <div class="phase-step"><div class="phase-dot" id="pd2"></div><span class="phase-label">聚焦</span></div>
      <div class="phase-step"><div class="phase-dot" id="pd3"></div><span class="phase-label">共振</span></div>
    </div>
  </div>
</div>

<script>
(function() {
  const SVG_NS = 'http://www.w3.org/2000/svg';
  const svg = document.getElementById('mainSvg');
  const radiationGroup = document.getElementById('radiationGroup');
  const waveGroup = document.getElementById('waveGroup');
  const moleculeGroup = document.getElementById('moleculeGroup');

  // 状态
  let ceramicTemp = 900; // °C
  let animFrame = 0;
  let phase = 0; // 0-3 对应四个阶段
  let phaseTimer = 0;
  const PHASE_DURATION = 120; // 帧数

  // 光谱参数
  function getPeakWavelength(tempC) {
    const tempK = tempC + 273.15;
    return 2898 / tempK; // μm
  }
  function getMatchScore(wavelength) {
    // 水吸收带 2.7-3.2μm,峰值 ~2.9μm
    const center = 2.9;
    const sigma = 0.25;
    return Math.exp(-Math.pow(wavelength - center, 2) / (2 * sigma * sigma));
  }

  // ====== 创建水分子 ======
  const moleculeData = [];
  const MOLECULE_COUNT = 14;
  for (let i = 0; i < MOLECULE_COUNT; i++) {
    const mx = 400 + Math.random() * 400;
    const my = 100 + Math.random() * 120;
    const angle = Math.random() * Math.PI * 2;
    moleculeData.push({ x: mx, y: my, angle, baseAngle: angle, vibAmp: 0 });
  }

  function createMolecule(d) {
    const g = document.createElementNS(SVG_NS, 'g');
    g.setAttribute('transform', `translate(${d.x}, ${d.y}) rotate(${d.angle * 180 / Math.PI})`);

    // O 原子
    const o = document.createElementNS(SVG_NS, 'circle');
    o.setAttribute('cx', '0'); o.setAttribute('cy', '0');
    o.setAttribute('r', '5'); o.setAttribute('fill', '#1565c0');
    g.appendChild(o);

    // H1
    const h1 = document.createElementNS(SVG_NS, 'circle');
    h1.setAttribute('cx', '-6'); h1.setAttribute('cy', '-5');
    h1.setAttribute('r', '3'); h1.setAttribute('fill', '#42a5f5');
    g.appendChild(h1);

    // H2
    const h2 = document.createElementNS(SVG_NS, 'circle');
    h2.setAttribute('cx', '6'); h2.setAttribute('cy', '-5');
    h2.setAttribute('r', '3'); h2.setAttribute('fill', '#42a5f5');
    g.appendChild(h2);

    // 键
    const b1 = document.createElementNS(SVG_NS, 'line');
    b1.setAttribute('x1', '-3.5'); b1.setAttribute('y1', '-2.5');
    b1.setAttribute('x2', '-5'); b1.setAttribute('y2', '-3.5');
    b1.setAttribute('stroke', '#90caf9'); b1.setAttribute('stroke-width', '1.2');
    g.appendChild(b1);

    const b2 = document.createElementNS(SVG_NS, 'line');
    b2.setAttribute('x1', '3.5'); b2.setAttribute('y1', '-2.5');
    b2.setAttribute('x2', '5'); b2.setAttribute('y2', '-3.5');
    b2.setAttribute('stroke', '#90caf9'); b2.setAttribute('stroke-width', '1.2');
    g.appendChild(b2);

    // 发光效果(共振时)
    const glow = document.createElementNS(SVG_NS, 'circle');
    glow.setAttribute('cx', '0'); glow.setAttribute('cy', '0');
    glow.setAttribute('r', '10'); glow.setAttribute('fill', 'none');
    glow.setAttribute('stroke', '#42a5f5'); glow.setAttribute('stroke-width', '0.8');
    glow.setAttribute('opacity', '0');
    g.appendChild(glow);

    d.element = g;
    d.glowEl = glow;
    d.h1El = h1;
    d.h2El = h2;
    moleculeGroup.appendChild(g);
  }
  moleculeData.forEach(createMolecule);

  // ====== 辐射粒子系统 ======
  const particles = [];
  const PARTICLE_COUNT = 30;

  // 射线定义
  const rayPaths = [
    // 直射
    { type: 'direct', x1: 560, y1: 525, x2: 560, y2: 248 },
    { type: 'direct', x1: 600, y1: 525, x2: 600, y2: 248 },
    { type: 'direct', x1: 640, y1: 525, x2: 640, y2: 248 },
    // 反射 - 左
    { type: 'reflect', x1: 510, y1: 540, cpx: 310, cpy: 465, x2: 460, y2: 248 },
    { type: 'reflect', x1: 500, y1: 575, cpx: 255, cpy: 530, x2: 410, y2: 248 },
    // 反射 - 右
    { type: 'reflect', x1: 690, y1: 540, cpx: 890, cpy: 465, x2: 740, y2: 248 },
    { type: 'reflect', x1: 700, y1: 575, cpx: 945, cpy: 530, x2: 790, y2: 248 },
  ];

  function bezierPoint(t, p0x, p0y, cpx, cpy, p1x, p1y) {
    const mt = 1 - t;
    return {
      x: mt * mt * p0x + 2 * mt * t * cpx + t * t * p1x,
      y: mt * mt * p0y + 2 * mt * t * cpy + t * t * p1y
    };
  }

  function lerp(a, b, t) { return a + (b - a) * t; }

  function createParticle() {
    const rayIdx = Math.floor(Math.random() * rayPaths.length);
    const ray = rayPaths[rayIdx];
    const el = document.createElementNS(SVG_NS, 'circle');
    el.setAttribute('r', '2.5');
    el.setAttribute('fill', '#00e5ff');
    el.setAttribute('opacity', '0');
    radiationGroup.appendChild(el);

    return {
      el,
      ray,
      t: Math.random(),
      speed: 0.004 + Math.random() * 0.004,
      active: true
    };
  }

  for (let i = 0; i < PARTICLE_COUNT; i++) {
    particles.push(createParticle());
  }

  // ====== 波纹效果 ======
  const waveRings = [];
  const WAVE_COUNT = 5;
  for (let i = 0; i < WAVE_COUNT; i++) {
    const el = document.createElementNS(SVG_NS, 'ellipse');
    el.setAttribute('cx', '600');
    el.setAttribute('cy', '525');
    el.setAttribute('rx', '0');
    el.setAttribute('ry', '0');
    el.setAttribute('fill', 'none');
    el.setAttribute('stroke', '#00e5ff');
    el.setAttribute('stroke-width', '1');
    el.setAttribute('opacity', '0');
    waveGroup.appendChild(el);
    waveRings.push({ el, phase: i / WAVE_COUNT });
  }

  // ====== 绘制静态射线参考线 ======
  rayPaths.forEach(ray => {
    const line = document.createElementNS(SVG_NS, 'line');
    if (ray.type === 'direct') {
      line.setAttribute('x1', ray.x1); line.setAttribute('y1', ray.y1);
      line.setAttribute('x2', ray.x2); line.setAttribute('y2', ray.y2);
    }
    line.setAttribute('stroke', 'rgba(0,229,255,0.06)');
    line.setAttribute('stroke-width', '1');
    line.setAttribute('stroke-dasharray', '4,6');
    radiationGroup.insertBefore(line, radiationGroup.firstChild);

    if (ray.type === 'reflect') {
      const path = document.createElementNS(SVG_NS, 'path');
      path.setAttribute('d', `M ${ray.x1},${ray.y1} Q ${ray.cpx},${ray.cpy} ${ray.x2},${ray.y2}`);
      path.setAttribute('fill', 'none');
      path.setAttribute('stroke', 'rgba(0,229,255,0.06)');
      path.setAttribute('stroke-width', '1');
      path.setAttribute('stroke-dasharray', '4,6');
      radiationGroup.insertBefore(path, radiationGroup.firstChild);
    }
  });

  // ====== 反射点高光 ======
  const reflectPoints = [
    { x: 310, y: 465 }, { x: 255, y: 530 },
    { x: 890, y: 465 }, { x: 945, y: 530 }
  ];
  reflectPoints.forEach(p => {
    const c = document.createElementNS(SVG_NS, 'circle');
    c.setAttribute('cx', p.x); c.setAttribute('cy', p.y);
    c.setAttribute('r', '3');
    c.setAttribute('fill', '#b0bec5');
    c.setAttribute('opacity', '0.15');
    c.setAttribute('filter', 'url(#softGlow)');
    waveGroup.appendChild(c);
  });

  // ====== 交互控制 ======
  const tempSlider = document.getElementById('tempSlider');
  const tempVal = document.getElementById('tempVal');
  const waveVal = document.getElementById('waveVal');
  const matchBadge = document.getElementById('matchBadge');
  const tempDisplay = document.getElementById('tempDisplay');
  const emissionLine = document.getElementById('emissionLine');
  const emissionArrow = document.getElementById('emissionArrow');
  const wavelengthLabel = document.getElementById('wavelengthLabel');
  const matchText = document.getElementById('matchText');

  tempSlider.addEventListener('input', function() {
    ceramicTemp = parseInt(this.value);
    updateDisplays();
  });

  function updateDisplays() {
    const wl = getPeakWavelength(ceramicTemp);
    const match = getMatchScore(wl);

    tempVal.textContent = ceramicTemp + '°C';
    waveVal.textContent = wl.toFixed(2) + 'μm';
    tempDisplay.textContent = ceramicTemp + '°C';

    // 光谱指示器位置(2μm=30px, 5μm=290px,线性映射)
    const specX = 30 + (wl - 2) / (5 - 2) * 260;
    emissionLine.setAttribute('x1', specX);
    emissionLine.setAttribute('x2', specX);
    emissionArrow.setAttribute('points', `${specX},58 ${specX-5},68 ${specX+5},68`);
    wavelengthLabel.setAttribute('x', specX);
    wavelengthLabel.textContent = wl.toFixed(2) + 'μm';

    if (match > 0.6) {
      matchBadge.className = 'match-badge optimal';
      matchBadge.textContent = '光谱匹配';
      matchText.textContent = 'MATCH';
      matchText.setAttribute('fill', '#76ff03');
      emissionLine.setAttribute('stroke', '#76ff03');
      emissionArrow.setAttribute('fill', '#76ff03');
      wavelengthLabel.setAttribute('fill', '#76ff03');
    } else {
      matchBadge.className = 'match-badge mismatch';
      matchBadge.textContent = '波长偏离';
      matchText.textContent = 'MISMATCH';
      matchText.setAttribute('fill', '#ff3d00');
      emissionLine.setAttribute('stroke', '#ff3d00');
      emissionArrow.setAttribute('fill', '#ff3d00');
      wavelengthLabel.setAttribute('fill', '#ff3d00');
    }
  }

  // ====== 主动画循环 ======
  function animate() {
    animFrame++;
    phaseTimer++;

    // 阶段循环
    if (phaseTimer > PHASE_DURATION) {
      phaseTimer = 0;
      phase = (phase + 1) % 4;
    }

    // 更新阶段指示器
    for (let i = 0; i < 4; i++) {
      const dot = document.getElementById('pd' + i);
      dot.className = 'phase-dot' + (i === phase ? ' active' : '');
    }

    const wl = getPeakWavelength(ceramicTemp);
    const match = getMatchScore(wl);

    // ---- 更新辐射粒子 ----
    const rayOpacity = phase >= 1 ? Math.min(1, (phaseTimer / 30)) : 0.3;
    particles.forEach(p => {
      p.t += p.speed * (0.5 + match * 1.5);
      if (p.t > 1) {
        p.t = 0;
        p.ray = rayPaths[Math.floor(Math.random() * rayPaths.length)];
      }

      let pos;
      if (p.ray.type === 'direct') {
        pos = { x: lerp(p.ray.x1, p.ray.x2, p.t), y: lerp(p.ray.y1, p.ray.y2, p.t) };
      } else {
        pos = bezierPoint(p.t, p.ray.x1, p.ray.y1, p.ray.cpx, p.ray.cpy, p.ray.x2, p.ray.y2);
      }

      const alpha = Math.sin(p.t * Math.PI) * rayOpacity * (0.5 + match * 0.5);
      p.el.setAttribute('cx', pos.x);
      p.el.setAttribute('cy', pos.y);
      p.el.setAttribute('opacity', alpha.toFixed(3));

      // 颜色根据匹配度变化
      if (match > 0.6) {
        p.el.setAttribute('fill', '#00e5ff');
        p.el.setAttribute('r', (2 + match * 1.5).toFixed(1));
      } else {
        p.el.setAttribute('fill', '#ff8f00');
        p.el.setAttribute('r', '2');
      }

      // 到达锅底时的爆发效果
      if (p.t > 0.9 && match > 0.6) {
        p.el.setAttribute('filter', 'url(#glowCyan)');
      } else {
        p.el.removeAttribute('filter');
      }
    });

    // ---- 更新波纹 ----
    waveRings.forEach(w => {
      w.phase += 0.006 * (0.5 + match);
      if (w.phase > 1) w.phase -= 1;

      const r = w.phase * 80;
      const ry = r * 0.3;
      const alpha = (1 - w.phase) * 0.3 * (phase >= 1 ? 1 : 0.2);

      w.el.setAttribute('rx', r.toFixed(1));
      w.el.setAttribute('ry', ry.toFixed(1));
      w.el.setAttribute('opacity', alpha.toFixed(3));

      if (match > 0.6) {
        w.el.setAttribute('stroke', '#00e5ff');
      } else {
        w.el.setAttribute('stroke', '#ff8f00');
      }
    });

    // ---- 更新水分子振动 ----
    const vibIntensity = match * (phase >= 3 ? 1 : 0.3);
    moleculeData.forEach((d, i) => {
      const timeOffset = i * 0.7;
      const vibX = Math.sin(animFrame * 0.08 + timeOffset) * vibIntensity * 4;
      const vibY = Math.cos(animFrame * 0.1 + timeOffset) * vibIntensity * 3;
      const rotAngle = d.baseAngle * 180 / Math.PI + Math.sin(animFrame * 0.06 + timeOffset) * vibIntensity * 15;

      // O-H 键伸缩
      const stretch = 1 + Math.sin(animFrame * 0.12 + timeOffset) * vibIntensity * 0.3;
      d.h1El.setAttribute('cx', (-6 * stretch).toFixed(1));
      d.h2El.setAttribute('cx', (6 * stretch).toFixed(1));

      d.element.setAttribute('transform',
        `translate(${(d.x + vibX).toFixed(1)}, ${(d.y + vibY).toFixed(1)}) rotate(${rotAngle.toFixed(1)})`);

      // 共振光晕
      const glowAlpha = vibIntensity * 0.5 * (0.5 + 0.5 * Math.sin(animFrame * 0.1 + timeOffset));
      d.glowEl.setAttribute('opacity', glowAlpha.toFixed(3));
      if (match > 0.6) {
        d.glowEl.setAttribute('stroke', '#42a5f5');
        d.oParent = d.element.querySelector('circle');
      } else {
        d.glowEl.setAttribute('stroke', '#546e7a');
      }
    });

    // ---- 火焰强度随温度变化 ----
    const flameGroup = document.getElementById('flameGroup');
    const flameScale = 0.7 + (ceramicTemp - 700) / 500 * 0.5;
    flameGroup.style.transform = `scaleY(${flameScale.toFixed(2)})`;

    requestAnimationFrame(animate);
  }

  // 初始化
  updateDisplays();
  animate();

  // 自动阶段切换动画(连续循环展示四个阶段)
  // 阶段已在 animate() 中自动循环

})();
</script>
</body>
</html>

实现说明

本动画以 "热-辐射-吸收"频率绝对协调 为核心叙事,采用暗色科技仪器美学(Technical-Noir),通过以下设计实现 IFR 思想的可视化:

视觉架构

  • 纵剖面视图:从下至上依次为多孔陶瓷火盖→抛物面聚能盘→辐射传输区→微孔锅底→水分子层,清晰呈现能量转化路径
  • 四阶段自动循环:蓄热→辐射→聚焦→共振,底部指示器实时标注当前阶段
  • 光谱匹配面板(左下):实时显示维恩位移定律计算的峰值波长与水分子吸收带(2.7-3.2μm)的重合度

IFR 核心表达

  • 陶瓷自身即为"波长变换器"——无需额外能源,仅靠材料特性将1200°C明火降频为900°C辐射体
  • 抛物面聚能盘为零能耗聚能器——纯粹几何资源利用,将散射红外重定向至锅底
  • 水分子共振动画直观展示"光谱匹配替代温度堆砌":当波长落入吸收带,分子剧烈振动(O-H键伸缩);偏离时振动衰减

交互控制

  • 温度滑块(700-1200°C):拖动可观察波长偏移,当偏离900°C最佳工作点时,辐射粒子变橙、水分子振动减弱、匹配状态切换为"波长偏离"
  • 匹配度通过粒子颜色/大小/速度、分子振幅、波纹强度三重反馈同步呈现
积分规则:第一轮对话扣减6分,后续每轮扣4分