独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>中频感应振动流化床谷物干燥系统 - IFR理想解演示</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color: #050508;
--grid-color: rgba(30, 41, 59, 0.5);
--cyan-glow: #00f0ff;
--magma-glow: #ff3300;
--grain-color: #fbbf24;
--machine-stroke: #334155;
--text-muted: #64748b;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: var(--bg-color);
color: #fff;
font-family: 'JetBrains Mono', monospace;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
#animation-container {
width: 100%;
height: 100vh;
max-width: 100vw;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
svg {
width: 100%;
height: 100%;
max-height: 900px;
filter: drop-shadow(0 0 20px rgba(0, 240, 255, 0.05));
}
.hud-text {
font-size: 12px;
fill: var(--text-muted);
pointer-events: none;
letter-spacing: 1px;
}
.hud-title {
font-size: 14px;
fill: var(--cyan-glow);
font-weight: bold;
letter-spacing: 2px;
}
.hud-value {
fill: #fff;
font-weight: bold;
}
/* 动画定义 */
@keyframes pulse-cyan {
0%, 100% { opacity: 0.3; filter: brightness(1); }
50% { opacity: 0.8; filter: brightness(1.5); }
}
@keyframes vibrate {
0%, 100% { transform: translateY(0); }
25% { transform: translateY(-3px); }
75% { transform: translateY(3px); }
}
@keyframes flow-wave {
0% { stroke-dashoffset: 100; }
100% { stroke-dashoffset: 0; }
}
@keyframes steam-rise {
0% { transform: translateY(0) scale(1); opacity: 0; }
20% { opacity: 0.6; }
100% { transform: translateY(-80px) scale(2); opacity: 0; }
}
@keyframes drum-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.coil-glow {
animation: pulse-cyan 2s infinite ease-in-out;
}
.vibrating-bed {
animation: vibrate 0.1s infinite linear;
}
.magnetic-wave {
stroke-dasharray: 10 15;
animation: flow-wave 1s infinite linear;
}
.drum-group {
transform-origin: 950px 400px;
animation: drum-spin 4s infinite linear;
}
/* UI Overlay */
.controls {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 2rem;
background: rgba(15, 23, 42, 0.8);
border: 1px solid var(--machine-stroke);
padding: 1rem 2rem;
border-radius: 8px;
backdrop-filter: blur(10px);
z-index: 10;
}
.slider-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.slider-group label {
font-size: 11px;
color: var(--text-muted);
display: flex;
justify-content: space-between;
}
.slider-group label span {
color: var(--cyan-glow);
font-weight: bold;
}
input[type=range] {
-webkit-appearance: none;
width: 150px;
background: var(--machine-stroke);
height: 4px;
border-radius: 2px;
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--cyan-glow);
cursor: pointer;
box-shadow: 0 0 10px var(--cyan-glow);
}
</style>
</head>
<body>
<div id="animation-container">
<!-- SVG Canvas (1200x700 居中显示,主体居中,文字边缘) -->
<svg id="scene" viewBox="0 0 1200 700" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 发光滤镜 -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-intense" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="heat-glow">
<feGaussianBlur stdDeviation="2" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 背景网格图案 -->
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="rgba(30,41,59,0.3)" stroke-width="1"/>
</pattern>
<!-- 机器纹理 -->
<linearGradient id="metal" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="50%" stop-color="#0f172a" />
<stop offset="100%" stop-color="#020617" />
</linearGradient>
</defs>
<!-- 1. 背景层 -->
<rect width="1200" height="700" fill="url(#grid)" />
<!-- HUD 边缘文字排版区 (非遮挡) -->
<g id="hud-top-left" transform="translate(30, 40)">
<text class="hud-title" x="0" y="0">SYS.IFR_TRIZ // 理想最终解</text>
<text class="hud-text" x="0" y="20">型号: IND-FLUID-800</text>
<text class="hud-text" x="0" y="40">状态: <tspan fill="#00f0ff">在线且稳定运转</tspan></text>
</g>
<g id="hud-bottom-left" transform="translate(30, 660)">
<circle cx="5" cy="-5" r="4" fill="#fbbf24" />
<text class="hud-text" x="15" y="0">谷物颗粒 (受热蒸发水分)</text>
<circle cx="5" cy="-25" r="4" fill="#94a3b8" />
<circle cx="5" cy="-25" r="4" fill="#ff3300" filter="url(#heat-glow)" opacity="0.8" />
<text class="hud-text" x="15" y="-20">磁性载热颗粒 (涡流发热源)</text>
<path d="M 0 -45 L 10 -45" stroke="#00f0ff" stroke-width="2" class="magnetic-wave" />
<text class="hud-text" x="15" y="-40">中频交变磁场区域</text>
</g>
<g id="hud-top-right" transform="translate(1000, 40)">
<text class="hud-text" x="0" y="0">实时监控参数_</text>
<rect x="0" y="10" width="160" height="1" fill="#334155" />
<text class="hud-text" x="0" y="30">中频频率: <tspan class="hud-value" id="val-freq">12.5 kHz</tspan></text>
<text class="hud-text" x="0" y="50">振动频率: <tspan class="hud-value">15 Hz</tspan></text>
<text class="hud-text" x="0" y="70">颗粒温度: <tspan class="hud-value" fill="#ff3300">45.0 °C</tspan></text>
<text class="hud-text" x="0" y="90">混合比例: <tspan class="hud-value">1 : 2.5</tspan></text>
<!-- 迷你波形图 -->
<path d="M 0 120 Q 10 110, 20 120 T 40 120 T 60 120 T 80 120 T 100 120 T 120 120 T 140 120"
fill="none" stroke="#00f0ff" stroke-width="1" class="magnetic-wave" />
</g>
<!-- 2. 主体设备层 (居中区域 x:150-1050) -->
<!-- 回收管道 (底部) -->
<path d="M 950 500 L 950 580 L 150 580 L 150 250" fill="none" stroke="#1e293b" stroke-width="30" stroke-linejoin="round" />
<path d="M 950 500 L 950 580 L 150 580 L 150 250" fill="none" stroke="#00f0ff" stroke-width="1" stroke-linejoin="round" stroke-dasharray="5 10" class="magnetic-wave" opacity="0.3"/>
<text class="hud-text" x="500" y="600" fill="#00f0ff" opacity="0.6">▲ 磁性颗粒循环回收路径</text>
<!-- 进料斗 (左侧) -->
<path d="M 100 100 L 250 100 L 200 250 L 150 250 Z" fill="url(#metal)" stroke="var(--machine-stroke)" stroke-width="2" />
<text class="hud-text" x="110" y="90">谷物与磁球混合入口</text>
<!-- 成品谷物出口 (右下) -->
<path d="M 820 480 L 900 480 L 900 600 L 820 600 Z" fill="none" stroke="var(--machine-stroke)" stroke-width="2" stroke-dasharray="4 4"/>
<text class="hud-text" x="830" y="615">干燥谷物收集区</text>
<!-- 振动流化床主体 (中央) -->
<g id="fluid-bed-system">
<!-- 静态外壳/支架 -->
<rect x="230" y="270" width="560" height="200" fill="none" stroke="#1e293b" stroke-width="4" rx="8" />
<!-- 振动部分 -->
<g class="vibrating-bed">
<!-- 床体底板 -->
<rect x="250" y="440" width="530" height="10" fill="#334155" rx="4" />
<!-- 支撑弹簧 -->
<path d="M 300 450 L 290 455 L 310 465 L 290 475 L 310 485 L 300 490 M 700 450 L 690 455 L 710 465 L 690 475 L 710 485 L 700 490" fill="none" stroke="#64748b" stroke-width="3" />
</g>
<!-- 中频感应线圈 (上/下阵列) -->
<g id="induction-coils">
<!-- 上方线圈 -->
<rect x="280" y="220" width="450" height="30" fill="#0f172a" stroke="#00f0ff" stroke-width="1" rx="4" />
<g class="coil-glow" fill="#00f0ff">
<rect x="290" y="225" width="20" height="20" rx="2" />
<rect x="330" y="225" width="20" height="20" rx="2" />
<rect x="370" y="225" width="20" height="20" rx="2" />
<rect x="410" y="225" width="20" height="20" rx="2" />
<rect x="450" y="225" width="20" height="20" rx="2" />
<rect x="490" y="225" width="20" height="20" rx="2" />
<rect x="530" y="225" width="20" height="20" rx="2" />
<rect x="570" y="225" width="20" height="20" rx="2" />
<rect x="610" y="225" width="20" height="20" rx="2" />
<rect x="650" y="225" width="20" height="20" rx="2" />
<rect x="690" y="225" width="20" height="20" rx="2" />
</g>
<!-- 下方线圈 -->
<rect x="280" y="480" width="450" height="30" fill="#0f172a" stroke="#00f0ff" stroke-width="1" rx="4" />
<g class="coil-glow" fill="#00f0ff">
<rect x="290" y="485" width="20" height="20" rx="2" />
<rect x="330" y="485" width="20" height="20" rx="2" />
<rect x="370" y="485" width="20" height="20" rx="2" />
<rect x="410" y="485" width="20" height="20" rx="2" />
<rect x="450" y="485" width="20" height="20" rx="2" />
<rect x="490" y="485" width="20" height="20" rx="2" />
<rect x="530" y="485" width="20" height="20" rx="2" />
<rect x="570" y="485" width="20" height="20" rx="2" />
<rect x="610" y="485" width="20" height="20" rx="2" />
<rect x="650" y="485" width="20" height="20" rx="2" />
<rect x="690" y="485" width="20" height="20" rx="2" />
</g>
<!-- 磁场指示线 -->
<g stroke="#00f0ff" stroke-width="1" opacity="0.2" class="magnetic-wave">
<path d="M 300 250 L 300 480 M 340 250 L 340 480 M 380 250 L 380 480 M 420 250 L 420 480 M 460 250 L 460 480 M 500 250 L 500 480 M 540 250 L 540 480 M 580 250 L 580 480 M 620 250 L 620 480 M 660 250 L 660 480 M 700 250 L 700 480" />
</g>
</g>
</g>
<text class="hud-text" x="460" y="210" fill="#00f0ff">中频交变磁场 (产生涡流)</text>
<text class="hud-text" x="460" y="530">振动流化床 (悬浮、翻动)</text>
<!-- 磁选滚筒 (右侧) -->
<g id="magnetic-separator" transform="translate(950, 400)">
<circle cx="0" cy="0" r="90" fill="none" stroke="var(--machine-stroke)" stroke-width="2" stroke-dasharray="10 5" />
<g class="drum-group">
<circle cx="0" cy="0" r="80" fill="url(#metal)" stroke="#334155" stroke-width="4" />
<!-- 滚筒内部磁极指示 -->
<path d="M -70 0 A 70 70 0 0 1 70 0" fill="none" stroke="#00f0ff" stroke-width="6" opacity="0.4" filter="url(#glow)"/>
<line x1="-80" y1="0" x2="80" y2="0" stroke="#334155" stroke-width="2" />
<line x1="0" y1="-80" x2="0" y2="80" stroke="#334155" stroke-width="2" />
</g>
<text class="hud-text" x="-35" y="-95" fill="#00f0ff">磁选分离滚筒</text>
</g>
<!-- 挡板 / 刮板 -->
<path d="M 940 490 L 980 480" stroke="#fbbf24" stroke-width="3" stroke-linecap="round"/>
<!-- 3. 粒子系统容器 (通过JS动态渲染) -->
<g id="steam-layer"></g>
<g id="particles-layer"></g>
</svg>
<!-- 交互控制面板 (悬浮于底部居中) -->
<div class="controls">
<div class="slider-group">
<label>中频磁场强度 <span>(感应加热)</span></label>
<input type="range" id="power-slider" min="0" max="100" value="80">
</div>
<div class="slider-group">
<label>流化床振动幅度 <span>(物理翻动)</span></label>
<input type="range" id="vibrate-slider" min="10" max="100" value="50">
</div>
</div>
</div>
<script>
// 常量与配置
const SVG_NS = "http://www.w3.org/2000/svg";
const particlesLayer = document.getElementById('particles-layer');
const steamLayer = document.getElementById('steam-layer');
const particles = [];
const steams = [];
let powerLevel = 80;
let vibrateLevel = 50;
// UI 绑定
document.getElementById('power-slider').addEventListener('input', (e) => {
powerLevel = parseInt(e.target.value);
document.getElementById('val-freq').textContent = (8 + (powerLevel / 100) * 7).toFixed(1) + ' kHz';
const coils = document.querySelectorAll('.coil-glow, .magnetic-wave');
coils.forEach(el => {
el.style.opacity = (powerLevel / 100);
});
});
document.getElementById('vibrate-slider').addEventListener('input', (e) => {
vibrateLevel = parseInt(e.target.value);
document.querySelector('.vibrating-bed').style.animationDuration = (0.2 - (vibrateLevel / 100) * 0.15) + 's';
});
class Particle {
constructor(type, startX, startY) {
this.type = type; // 'grain' (谷物) 或 'ball' (磁球)
this.x = startX;
this.y = startY;
this.vx = (Math.random() - 0.5) * 2;
this.vy = 2 + Math.random() * 2;
this.temp = type === 'ball' ? 25 : 25;
this.moisture = type === 'grain' ? 100 : 0;
this.radius = type === 'grain' ? 5 : 4;
this.element = document.createElementNS(SVG_NS, type === 'grain' ? 'ellipse' : 'circle');
this.glow = null;
if (type === 'grain') {
this.element.setAttribute('rx', this.radius + 1);
this.element.setAttribute('ry', this.radius - 1);
this.element.setAttribute('fill', '#fbbf24');
} else {
this.element.setAttribute('r', this.radius);
this.element.setAttribute('fill', '#94a3b8');
// 磁球发光层
this.glow = document.createElementNS(SVG_NS, 'circle');
this.glow.setAttribute('r', this.radius * 1.5);
this.glow.setAttribute('fill', '#ff3300');
this.glow.setAttribute('filter', 'url(#heat-glow)');
this.glow.setAttribute('opacity', '0');
particlesLayer.appendChild(this.glow);
}
particlesLayer.appendChild(this.element);
this.state = 'hopper'; // hopper -> bed -> separation -> end / recycle
this.updateDOM();
}
updateDOM() {
if (this.type === 'grain') {
this.element.setAttribute('cx', this.x);
this.element.setAttribute('cy', this.y);
// 随温度/干燥度改变颜色 (偏深橙)
const dryness = 100 - this.moisture;
const r = 251, g = 191 - (dryness * 0.8), b = 36 - (dryness * 0.2);
this.element.setAttribute('fill', `rgb(${r}, ${g}, ${b})`);
} else {
this.element.setAttribute('cx', this.x);
this.element.setAttribute('cy', this.y);
if (this.glow) {
this.glow.setAttribute('cx', this.x);
this.glow.setAttribute('cy', this.y);
// 温度映射到透明度 25度->0, 80度->1
let glowOpacity = Math.max(0, (this.temp - 30) / 50);
this.glow.setAttribute('opacity', glowOpacity.toString());
}
}
}
destroy() {
if (this.element.parentNode) this.element.parentNode.removeChild(this.element);
if (this.glow && this.glow.parentNode) this.glow.parentNode.removeChild(this.glow);
}
}
class Steam {
constructor(x, y) {
this.x = x;
this.y = y;
this.age = 0;
this.life = 60 + Math.random() * 40;
this.element = document.createElementNS(SVG_NS, 'circle');
this.element.setAttribute('r', 3 + Math.random() * 4);
this.element.setAttribute('fill', '#ffffff');
this.element.setAttribute('opacity', '0.4');
this.element.setAttribute('filter', 'url(#glow)');
steamLayer.appendChild(this.element);
}
update() {
this.age++;
this.y -= 1.5;
this.x += (Math.random() - 0.5) * 2;
this.element.setAttribute('cx', this.x);
this.element.setAttribute('cy', this.y);
this.element.setAttribute('opacity', 0.4 * (1 - this.age / this.life));
return this.age >= this.life;
}
destroy() {
if (this.element.parentNode) this.element.parentNode.removeChild(this.element);
}
}
// 动画主循环
let frame = 0;
function spawnParticles() {
// 在进料口生成,比例 谷物:磁球 = 2.5 : 1
if (frame % 3 === 0) {
particles.push(new Particle('grain', 160 + Math.random() * 40, 100));
particles.push(new Particle('grain', 160 + Math.random() * 40, 100));
}
if (frame % 7 === 0) {
particles.push(new Particle('ball', 160 + Math.random() * 40, 100));
}
}
function updatePhysics() {
for (let i = particles.length - 1; i >= 0; i--) {
let p = particles[i];
let isDead = false;
switch (p.state) {
case 'hopper':
p.y += p.vy;
if (p.y > 250) {
p.state = 'bed';
p.vx = 2 + Math.random() * 2;
}
break;
case 'bed':
// 物理模拟:重力与床底碰撞
p.vy += 0.2; // gravity
p.y += p.vy;
p.x += p.vx;
// 床底碰撞 (流化床振动给向上的力)
if (p.y > 430) {
p.y = 430;
// 振动幅度影响弹跳高度
p.vy = -(3 + (vibrateLevel / 100) * 4) * (0.8 + Math.random() * 0.4);
}
// 推进力 (向右流动)
if (p.vx < 1.5) p.vx += 0.1;
if (p.vx > 3) p.vx -= 0.1;
// 核心创新逻辑:磁球发热,谷物吸热
if (p.type === 'ball') {
// 在感应区,吸收能量升温
if (p.x > 280 && p.x < 730) {
p.temp += (powerLevel / 100) * 1.5;
if (p.temp > 80) p.temp = 80; // 最高温限制,避免过热
}
} else if (p.type === 'grain') {
// 极简碰撞模拟:基于概率和群体密度的热传导
// 假定谷物在床内稳定升温,水分下降
if (p.x > 280 && p.x < 730) {
p.temp += 0.1 + (powerLevel / 100) * 0.2;
if (p.temp > 45) { // 达到蒸发温度
p.moisture -= 0.5;
if (Math.random() < 0.05) { // 产生蒸汽视觉
steams.push(new Steam(p.x, p.y));
}
}
}
}
// 离开流化床
if (p.x > 800) {
p.state = 'separation';
p.vx = 3;
p.vy = -2;
}
break;
case 'separation':
// 到达磁选滚筒
p.y += p.vy;
p.x += p.vx;
p.vy += 0.2; // 重力
const drumX = 950, drumY = 400, r = 80;
const dx = p.x - drumX;
const dy = p.y - drumY;
const dist = Math.sqrt(dx*dx + dy*dy);
if (p.type === 'ball') {
// 磁球被滚筒吸附
if (dist < r + 20 && p.x < drumX + 20) {
// 强制贴附在表面旋转
const angle = Math.atan2(dy, dx);
// 根据滚筒旋转计算新位置
p.x = drumX + Math.cos(angle + 0.05) * (r + p.radius);
p.y = drumY + Math.sin(angle + 0.05) * (r + p.radius);
p.vx = 0; p.vy = 0;
// 底部脱离点 (通过刮板或磁场减弱区)
if (angle > Math.PI * 0.4 && angle < Math.PI * 0.6) {
p.state = 'recycle';
p.vx = 0;
p.vy = 2;
}
// 冷却
p.temp -= 0.5;
if (p.temp < 25) p.temp = 25;
}
} else {
// 谷物不受磁力,直接抛物线下落
if (p.y > 600) {
isDead = true; // 收集完成
}
}
break;
case 'recycle':
// 进入底部回收管道
if (p.y < 550 && p.x > 900) {
p.y += 4; // 掉入管道
} else if (p.y >= 550 && p.x > 150) {
p.y = 550;
p.x -= 6; // 在管道中向左移动
p.temp -= 0.2; // 继续冷却
} else if (p.x <= 150) {
p.x = 150;
p.y -= 6; // 提升回初始位置
if (p.y < 250) {
p.state = 'bed'; // 重新进入系统,模拟循环
p.vx = 2; p.vy = 0;
}
}
break;
}
if (isDead) {
p.destroy();
particles.splice(i, 1);
} else {
p.updateDOM();
}
}
// 更新蒸汽
for (let i = steams.length - 1; i >= 0; i--) {
if (steams[i].update()) {
steams[i].destroy();
steams.splice(i, 1);
}
}
}
function animate() {
frame++;
spawnParticles();
updatePhysics();
requestAnimationFrame(animate);
}
// 页面加载完成后直接启动,不需点击
window.addEventListener('DOMContentLoaded', () => {
// 初始化一些谷物在床内,避免初期太空
for(let i=0; i<40; i++) {
let p = new Particle(i%3==0?'ball':'grain', 300 + Math.random()*400, 350 + Math.random()*80);
p.state = 'bed';
particles.push(p);
}
animate();
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
