独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>蜂窝整流器流体动力学原理</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Jura:wght@400;600;700&display=swap');
:root {
--bg-color: #070a10;
--grid-color: rgba(41, 61, 90, 0.15);
--machine-fill: #121822;
--machine-stroke: #2a3f5a;
--highlight: #00ffcc;
--fluid-chaos: #0077ff;
--fluid-laminar: #00ffcc;
--text-main: #8ba3c0;
--text-accent: #ffffff;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: 'Jura', sans-serif;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 30px 30px;
background-position: center center;
}
#canvas-container {
position: relative;
width: 90vw;
height: 90vh;
max-width: 1400px;
max-height: 900px;
box-shadow: 0 0 100px rgba(0, 255, 204, 0.05) inset,
0 0 0 1px rgba(42, 63, 90, 0.5);
background: radial-gradient(circle at center, #0a101a 0%, #05070a 100%);
border-radius: 4px;
}
svg {
width: 100%;
height: 100%;
display: block;
}
/* Overlay Text Styling - Kept strictly to the edges, small size */
.annotation {
position: absolute;
font-size: 12px;
letter-spacing: 1px;
line-height: 1.4;
pointer-events: none;
}
.anno-title {
color: var(--highlight);
font-weight: 700;
font-size: 14px;
margin-bottom: 4px;
text-transform: uppercase;
}
.anno-top-left { top: 30px; left: 30px; }
.anno-middle-right { top: 50%; right: 30px; transform: translateY(-50%); text-align: right; }
.anno-bottom-left { bottom: 30px; left: 30px; }
.stat-box {
display: inline-block;
border: 1px solid rgba(0, 255, 204, 0.3);
background: rgba(0, 255, 204, 0.05);
padding: 4px 8px;
margin-top: 5px;
border-radius: 2px;
font-family: monospace;
color: var(--text-accent);
}
/* Animations */
@keyframes vibrate {
0% { transform: translate(0, 0) rotate(-15deg); }
25% { transform: translate(-1px, 1px) rotate(-15deg); }
50% { transform: translate(1px, -1px) rotate(-15deg); }
75% { transform: translate(-1px, -1px) rotate(-15deg); }
100% { transform: translate(0, 0) rotate(-15deg); }
}
.vibrating-screen {
transform-origin: center;
animation: vibrate 0.1s infinite linear;
}
@keyframes flowPulse {
0% { opacity: 0.6; }
50% { opacity: 1; }
100% { opacity: 0.6; }
}
.glow-effect {
animation: flowPulse 3s infinite ease-in-out;
}
</style>
</head>
<body>
<div id="canvas-container">
<!-- UI Overlays (Strictly constrained to corners/edges) -->
<div class="annotation anno-top-left">
<div class="anno-title">01 / 高能扰动区</div>
钻井液夹带高动能进入进料箱<br>
呈现高雷诺数无序湍流状态
</div>
<div class="annotation anno-middle-right">
<div class="anno-title">02 / IFR 整流核心</div>
<span style="color: #fff">蜂窝管束结构</span><br>
流体被迫细分,横向动能被管壁吸收<br>
实现从湍流向层流的强制转换<br>
<div class="stat-box">D=20mm | L=200mm</div>
</div>
<div class="annotation anno-bottom-left">
<div class="anno-title">03 / 理想均布液幕</div>
动能消散,均压流出<br>
零冲击落在振动筛面<br>
最大化筛网寿命与分离效率
</div>
<!-- Main SVG Animation -->
<svg viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- Glow Filters -->
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-blue" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="12" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Gradients -->
<linearGradient id="fluid-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="var(--fluid-chaos)" stop-opacity="0.8"/>
<stop offset="40%" stop-color="var(--fluid-chaos)" stop-opacity="0.9"/>
<stop offset="60%" stop-color="var(--fluid-laminar)" stop-opacity="0.9"/>
<stop offset="100%" stop-color="var(--fluid-laminar)" stop-opacity="0.4"/>
</linearGradient>
<linearGradient id="metal-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1a2535"/>
<stop offset="50%" stop-color="#2a3f5a"/>
<stop offset="100%" stop-color="#1a2535"/>
</linearGradient>
<!-- Patterns -->
<pattern id="honeycomb-pattern" width="16" height="30" patternUnits="userSpaceOnUse">
<path d="M 8 0 L 16 15 L 8 30 L 0 15 Z" fill="none" stroke="#2a3f5a" stroke-width="1.5" opacity="0.3"/>
</pattern>
<!-- Screen Mesh Pattern -->
<pattern id="mesh-pattern" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(15)">
<rect width="6" height="6" fill="none" stroke="#4a5f7a" stroke-width="0.5"/>
</pattern>
<clipPath id="rectifier-clip">
<rect x="400" y="300" width="400" height="150" />
</clipPath>
</defs>
<!-- ================= BACKGROUND TECHNICAL ELEMENTS ================= -->
<!-- Blueprint structural lines -->
<path d="M 600 0 L 600 800 M 0 400 L 1200 400" stroke="rgba(42, 63, 90, 0.3)" stroke-width="1" stroke-dasharray="10 10"/>
<circle cx="600" cy="400" r="300" fill="none" stroke="rgba(42, 63, 90, 0.1)" stroke-width="1"/>
<!-- Dimension Lines & Leader Lines for Annotations -->
<g stroke="var(--text-main)" stroke-width="1" opacity="0.5">
<!-- Top Left Leader -->
<polyline points="200,60 380,60 450,150" fill="none" />
<circle cx="450" cy="150" r="3" fill="var(--text-main)" />
<!-- Middle Right Leader -->
<polyline points="1000,400 850,400 800,375" fill="none" />
<circle cx="800" cy="375" r="3" fill="var(--highlight)" />
<!-- Bottom Left Leader -->
<polyline points="200,740 380,740 500,650" fill="none" />
<circle cx="500" cy="650" r="3" fill="var(--text-main)" />
<!-- Rectifier Dimensions (L=200) visual cue -->
<line x1="820" y1="300" x2="820" y2="450" stroke="var(--highlight)" stroke-dasharray="4 4"/>
<line x1="810" y1="300" x2="830" y2="300" stroke="var(--highlight)"/>
<line x1="810" y1="450" x2="830" y2="450" stroke="var(--highlight)"/>
</g>
<!-- ================= STATIC MACHINERY ================= -->
<!-- Feed Box Housing Top -->
<path d="M 450 0 L 450 150 L 350 250 L 350 300 L 850 300 L 850 250 L 750 150 L 750 0"
fill="none" stroke="var(--machine-stroke)" stroke-width="3" />
<!-- Fluid background mass (the chaotic volume) -->
<path d="M 452 0 L 452 150 L 352 250 L 352 300 L 848 300 L 848 250 L 748 150 L 748 0 Z"
fill="rgba(0, 119, 255, 0.1)"/>
<!-- The Honeycomb Rectifier Component (IFR Core) -->
<g transform="translate(400, 300)">
<!-- Casing -->
<rect x="0" y="0" width="400" height="150" fill="url(#metal-grad)" stroke="var(--machine-stroke)" stroke-width="4"/>
<!-- Honeycomb front texture -->
<rect x="2" y="2" width="396" height="146" fill="url(#honeycomb-pattern)"/>
<!-- Grid division lines (representing tubes) -->
<g stroke="#1a2535" stroke-width="2">
<line x1="40" y1="0" x2="40" y2="150"/>
<line x1="80" y1="0" x2="80" y2="150"/>
<line x1="120" y1="0" x2="120" y2="150"/>
<line x1="160" y1="0" x2="160" y2="150"/>
<line x1="200" y1="0" x2="200" y2="150"/>
<line x1="240" y1="0" x2="240" y2="150"/>
<line x1="280" y1="0" x2="280" y2="150"/>
<line x1="320" y1="0" x2="320" y2="150"/>
<line x1="360" y1="0" x2="360" y2="150"/>
</g>
<!-- Glow indication at exit -->
<rect x="0" y="145" width="400" height="5" fill="var(--highlight)" filter="url(#glow-cyan)" opacity="0.7"/>
</g>
<!-- Lower Housing -->
<path d="M 400 450 L 400 500 L 350 550" fill="none" stroke="var(--machine-stroke)" stroke-width="3" />
<path d="M 800 450 L 800 500 L 850 550" fill="none" stroke="var(--machine-stroke)" stroke-width="3" />
<!-- Vibrating Screen -->
<!-- Wrapped in a group for CSS vibration animation -->
<g class="vibrating-screen" transform="translate(600, 650) rotate(-15) translate(-600, -650)">
<!-- Support frame -->
<rect x="300" y="630" width="600" height="40" rx="4" fill="var(--machine-fill)" stroke="var(--machine-stroke)" stroke-width="3"/>
<!-- Screen Mesh -->
<rect x="310" y="625" width="580" height="10" fill="url(#mesh-pattern)" stroke="var(--highlight)" stroke-width="1"/>
<!-- Structural ribs -->
<path d="M 400 630 L 400 670 M 500 630 L 500 670 M 600 630 L 600 670 M 700 630 L 700 670 M 800 630 L 800 670" stroke="var(--machine-stroke)" stroke-width="4"/>
</g>
<!-- ================= DYNAMIC FLUID SYSTEM ================= -->
<!-- Base background curtain for the lower part -->
<path d="M 400 450 L 800 450 L 800 600 Q 600 650 400 550 Z"
fill="url(#fluid-gradient)" class="glow-effect" opacity="0.3"/>
<!-- Canvas for JS Particle System -->
<g id="particle-system"></g>
<!-- Foreground technical overlays (to hide particles clipping out) -->
<rect x="390" y="290" width="420" height="10" fill="var(--bg-color)" />
<path d="M 390 300 L 810 300" stroke="var(--machine-stroke)" stroke-width="4"/>
</svg>
</div>
<script>
/**
* Fluid Dynamics Particle System
* Illustrates the TRIZ IFR: Chaotic kinetic energy -> Orderly laminar flow
*/
const svgNS = "http://www.w3.org/2000/svg";
const particleContainer = document.getElementById('particle-system');
// System Parameters
const NUM_PARTICLES = 400;
const TUBE_WIDTH = 40;
const TUBES_START_X = 400;
const TUBES_START_Y = 300;
const TUBES_END_Y = 450;
const SCREEN_Y_BASE = 650;
let particles = [];
// Particle Class
class Particle {
constructor() {
this.element = document.createElementNS(svgNS, 'circle');
particleContainer.appendChild(this.element);
this.reset();
// Randomize start delay
this.y = Math.random() * -400;
}
reset() {
// Start at top
this.x = 450 + Math.random() * 300;
this.y = -20;
this.size = Math.random() * 2.5 + 1.5;
this.element.setAttribute('r', this.size);
// Turbulent Phase Variables
this.baseVx = (Math.random() - 0.5) * 8;
this.vy = Math.random() * 3 + 2;
this.phase = Math.random() * Math.PI * 2;
this.state = 'turbulent'; // 'turbulent', 'rectifying', 'laminar', 'screen'
this.targetTubeX = null;
this.updateStyle();
}
updateStyle() {
if (this.state === 'turbulent') {
this.element.setAttribute('fill', 'var(--fluid-chaos)');
this.element.style.filter = 'url(#glow-blue)';
this.element.setAttribute('opacity', Math.random() * 0.5 + 0.3);
} else if (this.state === 'rectifying') {
this.element.setAttribute('fill', 'var(--highlight)');
this.element.style.filter = 'url(#glow-cyan)';
this.element.setAttribute('opacity', 0.8);
} else if (this.state === 'laminar') {
this.element.setAttribute('fill', 'var(--fluid-laminar)');
this.element.style.filter = 'url(#glow-cyan)';
this.element.setAttribute('opacity', 0.9);
}
}
update() {
// State Machine based on Y position
if (this.y < TUBES_START_Y) {
// 1. Turbulent Zone (Inlet)
if (this.state !== 'turbulent') {
this.state = 'turbulent';
this.updateStyle();
}
// Add chaotic movement via sine waves
this.phase += 0.1;
const chaos = Math.sin(this.phase) * 4;
this.x += this.baseVx + chaos;
// Shape constraint (funneling into box)
if (this.y > 150) {
const progress = (this.y - 150) / 150;
const leftBound = 450 - (100 * progress);
const rightBound = 750 + (100 * progress);
if (this.x < leftBound) { this.x = leftBound; this.baseVx = Math.abs(this.baseVx); }
if (this.x > rightBound) { this.x = rightBound; this.baseVx = -Math.abs(this.baseVx); }
} else {
if (this.x < 450) { this.x = 450; this.baseVx *= -1; }
if (this.x > 750) { this.x = 750; this.baseVx *= -1; }
}
this.vy += 0.05; // Gravity acceleration
} else if (this.y >= TUBES_START_Y && this.y < TUBES_END_Y) {
// 2. Rectifying Zone (Inside Honeycomb)
if (this.state !== 'rectifying') {
this.state = 'rectifying';
this.updateStyle();
// Assign to a specific tube channel
const relativeX = this.x - TUBES_START_X;
const tubeIndex = Math.floor(relativeX / TUBE_WIDTH);
// Center particle in its respective tube
this.targetTubeX = TUBES_START_X + (tubeIndex * TUBE_WIDTH) + (TUBE_WIDTH / 2);
// Kill horizontal velocity, standardize vertical velocity (low Reynolds number simulation)
this.baseVx = 0;
this.vy = 4; // Constant, controlled speed
}
// Smoothly snap to center of tube
if (this.targetTubeX !== null) {
this.x += (this.targetTubeX - this.x) * 0.2;
}
} else if (this.y >= TUBES_END_Y && this.state !== 'screen') {
// 3. Laminar Curtain Zone (Falling)
if (this.state !== 'laminar') {
this.state = 'laminar';
this.updateStyle();
// Slight spread after exiting
this.baseVx = (Math.random() - 0.5) * 0.5;
}
this.x += this.baseVx;
this.vy += 0.1; // Gravity resumes, but uniformly
// Check collision with angled screen (Angle is approx 15 deg)
// Line equation for screen: y - 650 = tan(-15deg) * (x - 600)
// y = -0.267 * (x - 600) + 650
const screenCollisionY = -0.267 * (this.x - 600) + 650;
if (this.y >= screenCollisionY) {
this.state = 'screen';
this.y = screenCollisionY;
// Calculate vector along the screen
const speed = Math.sqrt(this.baseVx*this.baseVx + this.vy*this.vy) * 0.6; // lose energy on impact
this.vx = Math.cos(-15 * Math.PI / 180) * speed;
this.vy = Math.sin(-15 * Math.PI / 180) * speed;
}
} else if (this.state === 'screen') {
// 4. Flowing down the screen
this.x -= 5; // Move left along the angled screen
this.y += 5 * 0.267; // Follow the angle
this.element.setAttribute('opacity', Math.max(0, this.element.getAttribute('opacity') - 0.02));
// Reset if off screen
if (this.x < 250 || this.element.getAttribute('opacity') <= 0) {
this.reset();
return; // skip coordinate update this frame
}
}
this.y += this.vy;
// Final bounds check
if (this.y > 850) {
this.reset();
}
// Render
this.element.setAttribute('cx', this.x);
this.element.setAttribute('cy', this.y);
}
}
// Initialize particles
for (let i = 0; i < NUM_PARTICLES; i++) {
particles.push(new Particle());
}
// Animation Loop
function animate() {
for (let i = 0; i < particles.length; i++) {
particles[i].update();
}
requestAnimationFrame(animate);
}
// Start animation immediately on load
window.addEventListener('DOMContentLoaded', () => {
animate();
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
