独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>中频感应缓苏干燥系统 - IFR 原理可视化</title>
<style>
:root {
--bg-color: #07090f;
--grid-color: rgba(56, 189, 248, 0.05);
--text-main: #94a3b8;
--text-glow: #e2e8f0;
--heat-color: #ff4d00;
--cool-color: #00e5ff;
--grain-color: #f59e0b;
--machine-bg: #0f172a;
--machine-border: #1e293b;
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-main);
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
#visualization-container {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 40px 40px;
background-position: center center;
}
svg {
width: 100%;
height: 100%;
max-width: 1800px;
max-height: 1000px;
filter: drop-shadow(0 0 30px rgba(0, 0, 0, 0.8));
}
/* Peripheral Minimalist UI Overlay */
.overlay-ui {
position: absolute;
pointer-events: none;
font-size: 13px;
line-height: 1.5;
letter-spacing: 0.5px;
z-index: 10;
}
.top-left { top: 30px; left: 40px; }
.bottom-right { bottom: 30px; right: 40px; text-align: right; }
.title-block {
border-left: 3px solid var(--cool-color);
padding-left: 12px;
margin-bottom: 15px;
}
.title {
font-size: 16px;
font-weight: 600;
color: var(--text-glow);
letter-spacing: 1.5px;
text-transform: uppercase;
}
.subtitle {
font-size: 11px;
color: var(--cool-color);
opacity: 0.8;
font-family: monospace;
}
.legend-item {
display: flex;
align-items: center;
margin-bottom: 6px;
gap: 8px;
}
.legend-color {
width: 10px;
height: 10px;
border-radius: 50%;
}
.tag {
display: inline-block;
padding: 2px 6px;
background: rgba(15, 23, 42, 0.8);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
font-family: monospace;
color: var(--text-glow);
}
/* CSS Animations */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes dashFlow {
to { stroke-dashoffset: -40; }
}
@keyframes pulseGlow {
0% { filter: drop-shadow(0 0 8px var(--heat-color)); opacity: 0.8; }
50% { filter: drop-shadow(0 0 16px var(--heat-color)); opacity: 1; }
100% { filter: drop-shadow(0 0 8px var(--heat-color)); opacity: 0.8; }
}
.fan-blade {
transform-origin: 50% 50%;
animation: spin 0.8s linear infinite;
}
.air-stream-hot {
stroke-dasharray: 10 10;
animation: dashFlow 1s linear infinite;
opacity: 0.6;
}
.air-stream-cool {
stroke-dasharray: 10 10;
animation: dashFlow 1.5s linear infinite;
opacity: 0.5;
}
.induction-coil {
animation: pulseGlow 2s ease-in-out infinite;
}
</style>
</head>
<body>
<div id="visualization-container">
<!-- Minimal UI Overlays -->
<div class="overlay-ui top-left">
<div class="title-block">
<div class="title">TRIZ 最终理想解 (IFR)</div>
<div class="subtitle">中频感应低热缓苏干燥系统</div>
</div>
<div style="color: #64748b; max-width: 300px;">
矛盾消除:极少增加系统复杂度,利用分离时空(交替干燥/缓苏)与间接热风,实现高速排湿且谷温不超限。
</div>
</div>
<div class="overlay-ui bottom-right">
<div class="legend-item"><span class="legend-color" style="background: var(--heat-color); box-shadow: 0 0 8px var(--heat-color);"></span> 50-55℃ 穿透热风 (带走表层水)</div>
<div class="legend-item"><span class="legend-color" style="background: var(--cool-color); box-shadow: 0 0 8px var(--cool-color);"></span> 纯通风缓苏区 (内部水分外移)</div>
<div class="legend-item"><span class="legend-color" style="background: var(--grain-color);"></span> 谷物 (芯温 ≤ 42℃)</div>
<div style="margin-top: 10px; font-family: monospace; opacity: 0.7;">SYS.STATUS // ACTIVE.AUTO_RUN</div>
</div>
<!-- Main SVG Visualization -->
<svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Gradients -->
<linearGradient id="heatGrad" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#ff4d00" stop-opacity="0.9" />
<stop offset="100%" stop-color="#ff4d00" stop-opacity="0" />
</linearGradient>
<linearGradient id="coolGrad" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="#00e5ff" stop-opacity="0.6" />
<stop offset="100%" stop-color="#00e5ff" stop-opacity="0" />
</linearGradient>
<linearGradient id="machineBody" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- Filters -->
<filter id="glowHeat" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glowCool" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Patterns -->
<pattern id="meshBelt" width="20" height="10" patternUnits="userSpaceOnUse">
<path d="M 0,5 L 20,5 M 10,0 L 10,10" stroke="#475569" stroke-width="1" opacity="0.5" />
</pattern>
<!-- Components -->
<g id="fan">
<circle cx="0" cy="0" r="25" fill="#0f172a" stroke="#334155" stroke-width="2" />
<g class="fan-blade">
<path d="M 0,-5 C 10,-20 20,-20 0,-23 C -20,-20 -10,-20 0,-5 Z" fill="#64748b" />
<path d="M 5,0 C 20,10 20,20 23,0 C 20,-20 20,-10 5,0 Z" fill="#64748b" transform="rotate(120)" />
<path d="M 5,0 C 20,10 20,20 23,0 C 20,-20 20,-10 5,0 Z" fill="#64748b" transform="rotate(240)" />
<circle cx="0" cy="0" r="4" fill="#cbd5e1" />
</g>
</g>
<g id="heatExchanger">
<!-- Finned tube base -->
<rect x="-80" y="-15" width="160" height="30" fill="#334155" rx="5" />
<!-- Fins -->
<path d="M-70,-20 v40 M-60,-20 v40 M-50,-20 v40 M-40,-20 v40 M-30,-20 v40 M-20,-20 v40 M-10,-20 v40 M0,-20 v40 M10,-20 v40 M20,-20 v40 M30,-20 v40 M40,-20 v40 M50,-20 v40 M60,-20 v40 M70,-20 v40" stroke="#94a3b8" stroke-width="2" opacity="0.6"/>
<!-- Induction Coil -->
<path d="M -85,-10 Q -75,-25 -65,-10 T -45,-10 T -25,-10 T -5,-10 T 15,-10 T 35,-10 T 55,-10 T 75,-10 T 85,0"
fill="none" stroke="#ff4d00" stroke-width="4" class="induction-coil" />
<path d="M -85,10 Q -75,25 -65,10 T -45,10 T -25,10 T -5,10 T 15,10 T 35,10 T 55,10 T 75,10 T 85,0"
fill="none" stroke="#ff4d00" stroke-width="4" class="induction-coil" />
</g>
</defs>
<!-- Background structure elements -->
<!-- Zone Dividers -->
<path d="M 700 300 L 700 700 M 900 300 L 900 700" stroke="#334155" stroke-width="2" stroke-dasharray="5 5" />
<text x="500" y="250" fill="#ff4d00" font-size="14" font-family="monospace" text-anchor="middle" filter="url(#glowHeat)">ZONE 1: 干燥段 (20min) / 加热排湿</text>
<text x="800" y="250" fill="#00e5ff" font-size="14" font-family="monospace" text-anchor="middle" filter="url(#glowCool)">ZONE 2: 缓苏段 (10min) / 水分外移</text>
<text x="1100" y="250" fill="#ff4d00" font-size="14" font-family="monospace" text-anchor="middle" filter="url(#glowHeat)">ZONE 3: 干燥段 (20min) / 二次排湿</text>
<!-- Machine Casing -->
<path d="M 250 280 L 1350 280 L 1350 780 L 250 780 Z" fill="none" stroke="#1e293b" stroke-width="4" rx="10" />
<!-- Conveyor Belt -->
<rect x="230" y="520" width="1140" height="15" fill="url(#meshBelt)" stroke="#475569" stroke-width="2" rx="4" />
<!-- Roller Wheels -->
<circle cx="240" cy="527.5" r="12" fill="#1e293b" stroke="#64748b" stroke-width="2" />
<circle cx="1360" cy="527.5" r="12" fill="#1e293b" stroke="#64748b" stroke-width="2" />
<!-- Fans & Heat Exchangers Assembly -->
<!-- Zone 1: Drying -->
<use href="#heatExchanger" x="500" y="650" />
<use href="#fan" x="420" y="730" />
<use href="#fan" x="500" y="730" />
<use href="#fan" x="580" y="730" />
<!-- Zone 2: Tempering (No heat exchanger, only air) -->
<use href="#fan" x="800" y="730" />
<!-- Zone 3: Drying -->
<use href="#heatExchanger" x="1100" y="650" />
<use href="#fan" x="1020" y="730" />
<use href="#fan" x="1100" y="730" />
<use href="#fan" x="1180" y="730" />
<!-- Static Air Streams (Animated via CSS dashes) -->
<!-- Zone 1 -->
<path d="M 420 620 L 420 320 M 460 620 L 460 320 M 500 620 L 500 320 M 540 620 L 540 320 M 580 620 L 580 320"
stroke="url(#heatGrad)" stroke-width="6" fill="none" class="air-stream-hot" />
<!-- Zone 2 -->
<path d="M 760 700 L 760 320 M 800 700 L 800 320 M 840 700 L 840 320"
stroke="url(#coolGrad)" stroke-width="4" fill="none" class="air-stream-cool" />
<!-- Zone 3 -->
<path d="M 1020 620 L 1020 320 M 1060 620 L 1060 320 M 1100 620 L 1100 320 M 1140 620 L 1140 320 M 1180 620 L 1180 320"
stroke="url(#heatGrad)" stroke-width="6" fill="none" class="air-stream-hot" />
<!-- Exhaust Valves (Top) -->
<path d="M 480 280 L 480 250 L 520 250 L 520 280 Z" fill="#0f172a" stroke="#475569" stroke-width="2"/>
<path d="M 485 245 L 495 235 M 500 245 L 510 235 M 515 245 L 525 235" stroke="#ff4d00" stroke-width="2" class="air-stream-hot" stroke-dasharray="4 4" />
<path d="M 1080 280 L 1080 250 L 1120 250 L 1120 280 Z" fill="#0f172a" stroke="#475569" stroke-width="2"/>
<path d="M 1085 245 L 1095 235 M 1100 245 L 1110 235 M 1115 245 L 1125 235" stroke="#ff4d00" stroke-width="2" class="air-stream-hot" stroke-dasharray="4 4" />
<!-- Dynamic Containers for JS injected elements -->
<g id="particles-vapor"></g>
<g id="particles-grain"></g>
<!-- MACRO VIEW: The IFR Core Visualizer -->
<g transform="translate(800, 140)">
<circle cx="0" cy="0" r="55" fill="#0a0a0f" stroke="#334155" stroke-width="2" />
<circle cx="0" cy="0" r="60" fill="none" stroke="#475569" stroke-width="1" stroke-dasharray="4 4" />
<text x="0" y="-75" fill="#e2e8f0" font-size="12" font-family="monospace" text-anchor="middle" font-weight="bold">微观原理分析视窗</text>
<!-- Macro Grain -->
<circle id="macro-grain-surface" cx="0" cy="0" r="40" fill="none" stroke="#00e5ff" stroke-width="4" opacity="0.8" />
<circle id="macro-grain-core" cx="0" cy="0" r="38" fill="#f59e0b" opacity="0.8" />
<circle cx="0" cy="0" r="15" fill="#00e5ff" opacity="0.4" filter="url(#glowCool)" />
<!-- Moisture Migration Arrows (Visible in Tempering) -->
<g id="macro-migration" opacity="0">
<path d="M 0 -20 L 0 -35 M -4 -30 L 0 -35 L 4 -30" stroke="#00e5ff" stroke-width="2" fill="none" />
<path d="M 0 20 L 0 35 M -4 30 L 0 35 L 4 30" stroke="#00e5ff" stroke-width="2" fill="none" />
<path d="M 20 0 L 35 0 M 30 -4 L 35 0 L 30 4" stroke="#00e5ff" stroke-width="2" fill="none" />
<path d="M -20 0 L -35 0 M -30 -4 L -35 0 L -30 4" stroke="#00e5ff" stroke-width="2" fill="none" />
</g>
<!-- Status Text inside Macro View -->
<text id="macro-temp" x="0" y="5" fill="#0f172a" font-size="12" font-family="monospace" text-anchor="middle" font-weight="bold">T: 38℃</text>
<text id="macro-state" x="0" y="65" fill="#00e5ff" font-size="11" font-family="monospace" text-anchor="middle">水向表面扩散</text>
</g>
<!-- Macro View Connectors -->
<path id="macro-tracker-line" d="M 800 200 L 800 500" stroke="#475569" stroke-width="1" stroke-dasharray="4 4" fill="none" />
<circle id="macro-tracker-dot" cx="800" cy="500" r="4" fill="none" stroke="#00e5ff" stroke-width="2" />
</svg>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const grainContainer = document.getElementById('particles-grain');
const vaporContainer = document.getElementById('particles-vapor');
// Macro view elements
const macroSurface = document.getElementById('macro-grain-surface');
const macroMigration = document.getElementById('macro-migration');
const macroTemp = document.getElementById('macro-temp');
const macroState = document.getElementById('macro-state');
const trackerLine = document.getElementById('macro-tracker-line');
const trackerDot = document.getElementById('macro-tracker-dot');
const ZONE_START = 260;
const ZONE_END = 1340;
const Y_BASE = 510;
const NUM_GRAINS = 120;
class Vapor {
constructor(x, y) {
this.x = x + (Math.random() * 20 - 10);
this.y = y;
this.life = 1.0;
this.speed = Math.random() * 1.5 + 1;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", Math.random() * 2 + 1);
this.el.setAttribute("fill", "#00e5ff");
vaporContainer.appendChild(this.el);
}
update() {
this.y -= this.speed;
this.life -= 0.015;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life));
return this.life > 0;
}
remove() {
this.el.remove();
}
}
class Grain {
constructor(x, offsetLayer) {
this.x = x;
this.y = Y_BASE - offsetLayer * 12 + (Math.random() * 4 - 2);
this.internalMoisture = 100;
this.surfaceMoisture = 60;
this.temp = 25; // ambient start
this.g = document.createElementNS("http://www.w3.org/2000/svg", "g");
// Core
this.core = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.core.setAttribute("r", 5);
this.core.setAttribute("fill", "#f59e0b");
// Surface moisture ring
this.surface = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.surface.setAttribute("r", 6.5);
this.surface.setAttribute("fill", "none");
this.surface.setAttribute("stroke", "#00e5ff");
this.surface.setAttribute("stroke-width", "1.5");
this.g.appendChild(this.core);
this.g.appendChild(this.surface);
grainContainer.appendChild(this.g);
}
update() {
// Conveyor speed
this.x += 0.4;
if (this.x > ZONE_END) {
this.x = ZONE_START;
this.internalMoisture = 100;
this.surfaceMoisture = 60;
this.temp = 25;
}
// Physics based on Zones
let zone = 0; // 0: enter/exit, 1: dry1, 2: temper, 3: dry2
if (this.x > 300 && this.x < 700) zone = 1;
else if (this.x >= 700 && this.x <= 900) zone = 2;
else if (this.x > 900 && this.x < 1300) zone = 3;
if (zone === 1 || zone === 3) {
// Drying: Surface moisture evaporates, temp rises slightly but capped
if (this.surfaceMoisture > 5) {
this.surfaceMoisture -= 0.15;
// Spawn vapor randomly
if (Math.random() < 0.05) vapors.push(new Vapor(this.x, this.y));
}
if (this.temp < 41) this.temp += 0.05;
} else if (zone === 2) {
// Tempering: Internal moves to surface, temp drops
if (this.internalMoisture > 20 && this.surfaceMoisture < 80) {
this.internalMoisture -= 0.1;
this.surfaceMoisture += 0.08; // slight loss
}
if (this.temp > 32) this.temp -= 0.05;
} else {
// Ambient cooling
if (this.temp > 25) this.temp -= 0.1;
}
// Update Visuals
this.g.setAttribute("transform", `translate(${this.x}, ${this.y})`);
this.surface.setAttribute("opacity", Math.max(0, this.surfaceMoisture / 100));
// Temp color shift (Core turns more orange as it heats, but never red due to low temp limit)
const red = 245;
const green = Math.max(120, 158 - (this.temp - 25) * 2); // 158 is amber green
this.core.setAttribute("fill", `rgb(${red}, ${green}, 11)`);
return { x: this.x, y: this.y, zone, temp: this.temp, surfM: this.surfaceMoisture };
}
}
const grains = [];
const vapors = [];
// Initialize grains distributed along the belt
for (let i = 0; i < NUM_GRAINS; i++) {
const startX = ZONE_START + (Math.random() * (ZONE_END - ZONE_START));
const layer = i % 3; // 3 layers of grain
grains.push(new Grain(startX, layer));
}
// Select a tracked grain for the Macro View
const trackedGrainIndex = Math.floor(NUM_GRAINS / 2);
function animate() {
// Update grains
let trackedStats = null;
grains.forEach((grain, index) => {
const stats = grain.update();
if (index === trackedGrainIndex) {
trackedStats = stats;
}
});
// Update vapors
for (let i = vapors.length - 1; i >= 0; i--) {
if (!vapors[i].update()) {
vapors[i].remove();
vapors.splice(i, 1);
}
}
// Update Macro View UI
if (trackedStats) {
trackerDot.setAttribute("cx", trackedStats.x);
trackerDot.setAttribute("cy", trackedStats.y);
// Bezier curve connector
trackerLine.setAttribute("d", `M 800 195 Q 800 350 ${trackedStats.x} ${trackedStats.y}`);
macroTemp.textContent = `T: ${trackedStats.temp.toFixed(1)}℃`;
macroSurface.setAttribute("stroke-width", Math.max(1, (trackedStats.surfM / 100) * 8));
if (trackedStats.zone === 1 || trackedStats.zone === 3) {
macroState.textContent = "快速气流带走表层水";
macroState.setAttribute("fill", "#ff4d00");
macroMigration.setAttribute("opacity", "0");
macroTemp.setAttribute("fill", "#ff4d00");
} else if (trackedStats.zone === 2) {
macroState.textContent = "内部水分向表面扩散";
macroState.setAttribute("fill", "#00e5ff");
macroMigration.setAttribute("opacity", "1");
macroTemp.setAttribute("fill", "#00e5ff");
// Rotate migration arrows for active feel
const rot = (Date.now() / 20) % 360;
macroMigration.setAttribute("transform", `rotate(${rot})`);
} else {
macroState.textContent = "常温输送区";
macroState.setAttribute("fill", "#94a3b8");
macroMigration.setAttribute("opacity", "0");
macroTemp.setAttribute("fill", "#94a3b8");
}
}
requestAnimationFrame(animate);
}
// Auto-start animation
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
