独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>最终理想解 (IFR) - 全机械气动自适应止流系统</title>
<style>
:root {
--bg-color: #05080f;
--grid-color: #111a2e;
--fluid-color: #A3E635; /* Viscous drilling fluid */
--fluid-dim: rgba(163, 230, 53, 0.3);
--air-color: #00F0FF; /* Pneumatic power */
--metal-light: #94A3B8;
--metal-dark: #334155;
--accent: #FF6B35; /* Mechanical moving parts focus */
--text-muted: #64748B;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--metal-light);
font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
/* Minimal UI Overlay */
.ui-panel {
position: absolute;
pointer-events: none;
z-index: 10;
}
.ui-top-left {
top: 24px;
left: 24px;
max-width: 340px;
}
.ui-title {
font-size: 14px;
font-weight: 700;
color: #fff;
letter-spacing: 1px;
margin-bottom: 6px;
text-transform: uppercase;
}
.ui-desc {
font-size: 11px;
line-height: 1.6;
color: var(--text-muted);
}
.ui-desc span {
color: var(--air-color);
font-weight: 600;
}
/* Controls */
.controls-container {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 16px;
background: rgba(15, 23, 42, 0.7);
backdrop-filter: blur(8px);
padding: 10px 24px;
border-radius: 30px;
border: 1px solid var(--metal-dark);
z-index: 20;
}
.play-btn {
background: none;
border: none;
color: var(--air-color);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 4px;
transition: transform 0.2s;
}
.play-btn:hover {
transform: scale(1.1);
}
.play-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.slider-wrapper {
display: flex;
align-items: center;
gap: 12px;
width: 300px;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
background: transparent;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 12px;
width: 12px;
border-radius: 50%;
background: var(--air-color);
cursor: pointer;
margin-top: -5px;
box-shadow: 0 0 10px var(--air-color);
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 2px;
cursor: pointer;
background: var(--metal-dark);
border-radius: 1px;
}
.slider-label {
font-size: 10px;
color: var(--text-muted);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
/* SVG Styles */
svg.main-stage {
width: 100%;
height: 100%;
max-width: 1600px;
}
.blueprint-text {
font-family: ui-monospace, SFMono-Regular, monospace;
font-size: 11px;
fill: var(--text-muted);
letter-spacing: 0.5px;
}
.highlight-text {
fill: var(--air-color);
font-weight: bold;
}
.grid-line {
stroke: var(--grid-color);
stroke-width: 1;
}
.component {
fill: var(--bg-color);
stroke: var(--metal-light);
stroke-width: 2;
}
.component-dark {
fill: var(--metal-dark);
stroke: var(--metal-light);
stroke-width: 1;
}
.fluid {
fill: var(--fluid-color);
transition: fill 0.3s;
}
.fluid-line {
stroke: var(--fluid-color);
stroke-width: 4;
stroke-linecap: round;
fill: none;
}
.air-line {
stroke: var(--metal-dark);
stroke-width: 3;
fill: none;
stroke-dasharray: 4 4;
transition: stroke 0.3s, filter 0.3s;
}
.air-line.active {
stroke: var(--air-color);
filter: drop-shadow(0 0 5px var(--air-color));
animation: dashMove 0.5s linear infinite;
}
.mechanical-link {
stroke: var(--accent);
stroke-width: 3;
stroke-linecap: round;
fill: none;
}
.pivot {
fill: var(--accent);
stroke: var(--bg-color);
stroke-width: 2;
}
.wire-rope {
stroke: var(--metal-light);
stroke-width: 1.5;
stroke-dasharray: 6 3;
fill: none;
}
.glow {
filter: drop-shadow(0 0 8px var(--fluid-dim));
}
@keyframes dashMove {
to { stroke-dashoffset: -8; }
}
</style>
</head>
<body>
<!-- Minimal UI Annotations -->
<div class="ui-panel ui-top-left">
<div class="ui-title">最终理想解 (IFR) · 止流自适应机构</div>
<div class="ui-desc">
采用 TRIZ 思想剥离对外部电源与弱电控制的依赖。以现场气源为动力,利用流体势能(浮力)作为唯一感知输入。<br><br>
机械连杆 1:2 放大浮球行程,直接驱动 <span>气控换向阀</span> 抬升筛面并联动堰板减流。缓冲罐满载时,纯机械联动开启底端泄流阀。全过程 0 电子元件。
</div>
</div>
<!-- Interactive Controls -->
<div class="controls-container">
<button class="play-btn" id="playBtn" title="Play/Pause">
<!-- Pause Icon Default -->
<svg id="icon-pause" viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
<svg id="icon-play" viewBox="0 0 24 24" style="display:none;"><path d="M8 5v14l11-7z"/></svg>
</button>
<div class="slider-wrapper">
<span class="slider-label">CYCLE</span>
<input type="range" id="timeline" min="0" max="100" value="0" step="0.1">
<span class="slider-label" id="phase-label">0%</span>
</div>
</div>
<!-- Main SVG Animation Stage -->
<svg class="main-stage" viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid meet">
<!-- Definitions for grids and filters -->
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" class="grid-line" />
</pattern>
<linearGradient id="fluidGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#A3E635" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#65a30d" stop-opacity="0.9"/>
</linearGradient>
<clipPath id="screenClip">
<rect x="310" y="310" width="380" height="70" rx="4" />
</clipPath>
<clipPath id="tankClip">
<rect x="750" y="550" width="260" height="200" rx="8" />
</clipPath>
<filter id="neonAir" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Background Grid -->
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- STATIC BACKGROUND ELEMENTS -->
<g id="static-layer">
<!-- Inlet Pipe -->
<path d="M220,-10 L220,180 L280,180 L280,-10" class="component" />
<!-- Main Pivot Base -->
<path d="M720,400 L740,450 L700,450 Z" class="component-dark" />
<!-- Air Supply Point -->
<rect x="80" y="550" width="60" height="30" rx="4" class="component-dark" />
<text x="110" y="570" class="blueprint-text" text-anchor="middle">0.7MPa气源</text>
<!-- Buffer Tank Outline -->
<rect x="750" y="550" width="260" height="200" rx="8" class="component" />
<path d="M1010,700 L1070,700 L1070,740 L1010,740 Z" class="component" /> <!-- Drain Pipe -->
<!-- Wire Rope Pulleys -->
<circle cx="290" cy="100" r="10" class="component-dark" />
<circle cx="260" cy="100" r="10" class="component-dark" />
</g>
<!-- DYNAMIC ELEMENTS (Controlled by JS) -->
<g id="dynamic-layer">
<!-- Inflow Fluid -->
<path id="inlet-fluid" d="M230,180 L270,180 L270,320 L230,320 Z" fill="url(#fluidGrad)" class="glow" />
<!-- Weir Plate (Slides Y) -->
<rect id="weir-plate" x="275" y="100" width="10" height="90" rx="2" class="component" fill="#cbd5e1" />
<!-- Dump Fluid (Screen to Tank) -->
<path id="dump-fluid" d="M710,380 Q760,380 770,550 L790,550 Q780,390 710,390 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
<!-- Drain Fluid (Tank Out) -->
<path id="drain-fluid" d="M1040,740 L1070,740 L1070,850 L1040,850 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
<!-- SCREEN GROUP (Rotates around Pivot 720, 390) -->
<g id="screen-group" transform="rotate(0, 720, 390)">
<!-- Screen Box -->
<rect x="300" y="300" width="420" height="90" rx="6" class="component" />
<line x1="310" y1="380" x2="710" y2="380" stroke="#334155" stroke-width="4" stroke-dasharray="8 4" /> <!-- Screen mesh -->
<!-- Screen Liquid -->
<g clip-path="url(#screenClip)">
<rect id="screen-liquid" x="310" y="380" width="380" height="0" fill="url(#fluidGrad)" class="glow" />
</g>
<!-- Float 1 & Internal Linkage -->
<circle id="float1" cx="380" cy="380" r="16" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
<!-- Lever connected to float1 -->
<line id="lever1" x1="380" y1="380" x2="460" y2="250" class="mechanical-link" />
<circle cx="430" cy="300" r="4" class="pivot" /> <!-- Pivot for Lever 1 -->
</g>
<circle cx="720" cy="390" r="8" class="pivot" /> <!-- Main Screen Pivot -->
<!-- PNEUMATIC SYSTEM -->
<!-- Air Valve -->
<rect x="440" y="230" width="40" height="40" rx="4" class="component-dark" />
<text x="460" y="215" class="blueprint-text" text-anchor="middle">气控换向阀</text>
<!-- Air Lines -->
<path id="air-line-in" d="M140,565 L180,565 L180,250 L440,250" class="air-line" />
<path id="air-line-out" d="M480,250 L520,250 L520,620 L330,620 L330,580" class="air-line" />
<!-- Pneumatic Cylinder -->
<rect x="290" y="480" width="40" height="100" rx="4" class="component-dark" />
<rect id="cylinder-rod" x="302" y="380" width="16" height="100" class="component" fill="#e2e8f0" />
<circle id="cylinder-pin" cx="310" cy="380" r="5" class="pivot" />
<text x="260" y="530" class="blueprint-text" text-anchor="end">升降气缸</text>
<!-- Wire Rope Mechanism (Linked to Cylinder Rod) -->
<path id="wire-rope" d="M310,380 L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,100" class="wire-rope" />
<!-- BUFFER TANK SYSTEM -->
<!-- Tank Liquid -->
<g clip-path="url(#tankClip)">
<rect id="tank-liquid" x="750" y="750" width="260" height="0" fill="url(#fluidGrad)" class="glow" />
</g>
<!-- Float 2 & Butterfly Valve Linkage -->
<circle id="float2" cx="820" cy="730" r="20" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
<line id="lever2" x1="820" y1="730" x2="1040" y2="650" class="mechanical-link" />
<circle cx="950" cy="682" r="5" class="pivot" /> <!-- Pivot for Lever 2 -->
<!-- Butterfly Valve Assembly -->
<circle cx="1040" cy="720" r="24" class="component-dark" />
<line id="valve-disc" x1="1040" y1="696" x2="1040" y2="744" stroke="#e2e8f0" stroke-width="6" stroke-linecap="round" />
<text x="1100" y="725" class="blueprint-text highlight-text">纯机械联动蝶阀</text>
</g>
<!-- STATIC FOREGROUND ANNOTATIONS -->
<g id="annotations">
<!-- Screen Lift annotation -->
<line x1="160" y1="390" x2="280" y2="390" class="grid-line" stroke-dasharray="4" />
<path d="M220,390 L220,330" stroke="var(--text-muted)" stroke-width="1" marker-end="url(#arrow)" />
<text x="210" y="360" class="blueprint-text" text-anchor="end">抬升 100mm</text>
<!-- Float action annotation -->
<path d="M420,430 L380,430 L380,396" stroke="var(--text-muted)" stroke-width="1" fill="none" />
<text x="430" y="434" class="blueprint-text">液位行程 250mm</text>
<!-- Mechanical Ratio -->
<text x="430" y="280" class="blueprint-text">放大比 1:2</text>
<text x="880" y="660" class="blueprint-text">放大比联动</text>
</g>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--text-muted)" />
</marker>
</defs>
</svg>
<script>
/**
* Animation Math & Logic
* Driven by a 0-100 master timeline loop
*/
const state = {
t: 0,
playing: true,
speed: 0.15
};
// DOM Elements
const els = {
inlet_fluid: document.getElementById('inlet-fluid'),
weir_plate: document.getElementById('weir-plate'),
screen_group: document.getElementById('screen-group'),
screen_liquid: document.getElementById('screen-liquid'),
float1: document.getElementById('float1'),
lever1: document.getElementById('lever1'),
air_line_in: document.getElementById('air-line-in'),
air_line_out: document.getElementById('air-line-out'),
cylinder_rod: document.getElementById('cylinder-rod'),
cylinder_pin: document.getElementById('cylinder-pin'),
wire_rope: document.getElementById('wire-rope'),
dump_fluid: document.getElementById('dump-fluid'),
tank_liquid: document.getElementById('tank-liquid'),
float2: document.getElementById('float2'),
lever2: document.getElementById('lever2'),
valve_disc: document.getElementById('valve-disc'),
drain_fluid: document.getElementById('drain-fluid'),
timeline: document.getElementById('timeline'),
phase_label: document.getElementById('phase-label'),
play_btn: document.getElementById('playBtn'),
icon_play: document.getElementById('icon-play'),
icon_pause: document.getElementById('icon-pause')
};
// Easing functions for mechanical realism
function easeInOutQuad(x) {
return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
}
// Map a time segment to a 0-1 value
function mapTime(t, start, end) {
if (t <= start) return 0;
if (t >= end) return 1;
return easeInOutQuad((t - start) / (end - start));
}
function updateFrame() {
let t = state.t; // 0 to 100
// 1. Inflow fills screen (0-20), then drains (40-60)
let L1_fill = mapTime(t, 0, 20);
let L1_drain = mapTime(t, 40, 60);
let L1 = L1_fill - L1_drain; // 0.0 to 1.0
// 2. Float 1 directly follows L1 mechanically
let F1 = L1;
// 3. Pneumatic Valve triggers when F1 > 0.8.
// Cylinder actuates (20-35), drops (75-90)
let airOn = (t > 18 && t < 78);
let C1_up = mapTime(t, 20, 35);
let C1_down = mapTime(t, 75, 90);
let C1 = C1_up - C1_down; // 0.0 to 1.0
// 4. Fluid flow from screen to tank happens when screen is lifted
let dump_active = (t > 38 && t < 65);
// 5. Tank fills (40-65), drains (65-85)
let L2_fill = mapTime(t, 40, 65);
let L2_drain = mapTime(t, 65, 85);
let L2 = L2_fill - L2_drain; // 0.0 to 1.0
// 6. Tank Float directly follows L2
let F2 = L2;
// 7. Valve Disc linked to F2
let V1 = F2;
// --- DOM UPDATES ---
// Screen Liquid Height (Max 65px)
let liquidH = L1 * 65;
els.screen_liquid.setAttribute('y', 380 - liquidH);
els.screen_liquid.setAttribute('height', liquidH);
// Screen Float 1 (Moves up with liquid)
let f1_y = 364 - liquidH;
els.float1.setAttribute('cy', f1_y);
// Lever 1 Rotation based on F1
let lever1_angle = -F1 * 25; // max 25 deg up
els.lever1.setAttribute('transform', `rotate(${lever1_angle}, 430, 300)`);
// Connect line end to float (simplified local rotation logic)
// The float center moves, the rod stretches/rotates. Using SVG transforms makes this easier.
// For visual precision, just letting it point is enough for the principle.
// Air Logic
if (airOn) {
els.air_line_in.classList.add('active');
els.air_line_out.classList.add('active');
} else {
els.air_line_in.classList.remove('active');
els.air_line_out.classList.remove('active');
}
// Cylinder Extends (Max 60px)
let cyl_ext = C1 * 60;
els.cylinder_rod.setAttribute('y', 380 - cyl_ext);
els.cylinder_rod.setAttribute('height', 100 + cyl_ext);
els.cylinder_pin.setAttribute('cy', 380 - cyl_ext);
// Screen Box Tilt (Max 12 deg)
let screen_angle = C1 * 12;
els.screen_group.setAttribute('transform', `rotate(${-screen_angle}, 720, 390)`);
// Weir Plate & Wire Rope (closes 50% = drops 45px)
let weir_drop = C1 * 45;
els.weir_plate.setAttribute('transform', `translate(0, ${weir_drop})`);
// Adjust Inlet fluid visual based on weir
if (weir_drop > 0) {
els.inlet_fluid.setAttribute('d', `M230,${180+weir_drop} L270,${180+weir_drop} L270,320 L230,320 Z`);
} else {
els.inlet_fluid.setAttribute('d', `M230,180 L270,180 L270,320 L230,320 Z`);
}
// Dynamic Wire Rope Path
// Cylinder pin is at (310, 380 - cyl_ext). Pulley 1 at (290, 100), Pulley 2 at (260, 100). Weir at (280, 100 + weir_drop)
els.wire_rope.setAttribute('d', `M310,${380 - cyl_ext} L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,${100 + weir_drop}`);
// Dump Fluid Appearance
els.dump_fluid.setAttribute('opacity', dump_active ? (C1 * 0.9) : 0);
// Tank Liquid Height (Max 150px)
let tank_liquidH = L2 * 150;
els.tank_liquid.setAttribute('y', 750 - tank_liquidH);
els.tank_liquid.setAttribute('height', tank_liquidH);
// Tank Float 2
let f2_y = 730 - tank_liquidH;
els.float2.setAttribute('cy', f2_y);
// Lever 2 Rotation (Pivot 950, 682)
// Lever maps from float to valve.
let lever2_angle = -F2 * 35;
els.lever2.setAttribute('transform', `rotate(${lever2_angle}, 950, 682)`);
els.lever2.setAttribute('y1', f2_y);
// Butterfly Valve Disc Rotation (0 to 90deg)
let valve_angle = V1 * 90;
els.valve_disc.setAttribute('transform', `rotate(${valve_angle}, 1040, 720)`);
// Drain Fluid Appearance
els.drain_fluid.setAttribute('opacity', V1 > 0.1 ? V1 : 0);
// UI Updates
if (state.playing) {
els.timeline.value = t;
els.phase_label.innerText = Math.floor(t) + '%';
}
}
function loop() {
if (state.playing) {
state.t += state.speed;
if (state.t > 100) state.t = 0;
updateFrame();
}
requestAnimationFrame(loop);
}
// Interactivity
els.timeline.addEventListener('input', (e) => {
state.t = parseFloat(e.target.value);
els.phase_label.innerText = Math.floor(state.t) + '%';
updateFrame();
});
els.timeline.addEventListener('mousedown', () => { state.playing = false; updatePlayBtn(); });
els.timeline.addEventListener('mouseup', () => { state.playing = true; updatePlayBtn(); });
els.play_btn.addEventListener('click', () => {
state.playing = !state.playing;
updatePlayBtn();
});
function updatePlayBtn() {
if(state.playing) {
els.icon_pause.style.display = 'block';
els.icon_play.style.display = 'none';
} else {
els.icon_pause.style.display = 'none';
els.icon_play.style.display = 'block';
}
}
// Auto-start on load
window.addEventListener('DOMContentLoaded', () => {
state.t = 0;
state.playing = true;
updatePlayBtn();
loop();
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>最终理想解 (IFR) - 全机械气动自适应止流系统</title>
<style>
:root {
/* 调整为亮色主题(白底)适配的色彩规范 */
--bg-color: #ffffff;
--grid-color: #e2e8f0;
--fluid-color: #84cc16; /* 稍微加深以适应白底 */
--fluid-dim: rgba(132, 204, 22, 0.3);
--air-color: #0284c7; /* 加深的气动蓝色,确保在白底上清晰 */
--metal-light: #94a3b8;
--metal-dark: #334155;
--accent: #ea580c; /* 加深的机械运动件强调色 */
--text-muted: #64748b;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--metal-light);
font-family: 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
/* Minimal UI Overlay */
.ui-panel {
position: absolute;
pointer-events: none;
z-index: 10;
}
.ui-top-left {
top: 24px;
left: 24px;
max-width: 340px;
}
.ui-title {
font-size: 14px;
font-weight: 700;
color: #0f172a; /* 适配白底的深色标题 */
letter-spacing: 1px;
margin-bottom: 6px;
text-transform: uppercase;
}
.ui-desc {
font-size: 11px;
line-height: 1.6;
color: var(--text-muted);
}
.ui-desc span {
color: var(--air-color);
font-weight: 600;
}
/* Controls */
.controls-container {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 16px;
background: rgba(255, 255, 255, 0.8); /* 适配白底的半透明面板 */
backdrop-filter: blur(8px);
padding: 10px 24px;
border-radius: 30px;
border: 1px solid var(--grid-color);
z-index: 20;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.play-btn {
background: none;
border: none;
color: var(--air-color);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
padding: 4px;
transition: transform 0.2s;
}
.play-btn:hover {
transform: scale(1.1);
}
.play-btn svg {
width: 20px;
height: 20px;
fill: currentColor;
}
.slider-wrapper {
display: flex;
align-items: center;
gap: 12px;
width: 300px;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
background: transparent;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 12px;
width: 12px;
border-radius: 50%;
background: var(--air-color);
cursor: pointer;
margin-top: -5px;
box-shadow: 0 0 10px var(--air-color);
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 2px;
cursor: pointer;
background: var(--metal-light); /* 适配白底 */
border-radius: 1px;
}
.slider-label {
font-size: 10px;
color: var(--text-muted);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
/* SVG Styles */
svg.main-stage {
width: 100%;
height: 100%;
max-width: 1600px;
}
.blueprint-text {
font-family: ui-monospace, SFMono-Regular, monospace;
font-size: 11px;
fill: var(--text-muted);
letter-spacing: 0.5px;
}
.highlight-text {
fill: var(--air-color);
font-weight: bold;
}
.grid-line {
stroke: var(--grid-color);
stroke-width: 1;
}
.component {
fill: var(--bg-color);
stroke: var(--metal-light);
stroke-width: 2;
}
.component-dark {
fill: var(--metal-dark);
stroke: var(--metal-light);
stroke-width: 1;
}
.fluid {
fill: var(--fluid-color);
transition: fill 0.3s;
}
.fluid-line {
stroke: var(--fluid-color);
stroke-width: 4;
stroke-linecap: round;
fill: none;
}
.air-line {
stroke: var(--metal-dark);
stroke-width: 3;
fill: none;
stroke-dasharray: 4 4;
transition: stroke 0.3s, filter 0.3s;
}
.air-line.active {
stroke: var(--air-color);
filter: drop-shadow(0 0 3px var(--air-color));
animation: dashMove 0.5s linear infinite;
}
.mechanical-link {
stroke: var(--accent);
stroke-width: 3;
stroke-linecap: round;
fill: none;
}
.pivot {
fill: var(--accent);
stroke: var(--bg-color);
stroke-width: 2;
}
.wire-rope {
stroke: var(--metal-light);
stroke-width: 1.5;
stroke-dasharray: 6 3;
fill: none;
}
.glow {
filter: drop-shadow(0 0 8px var(--fluid-dim));
}
@keyframes dashMove {
to { stroke-dashoffset: -8; }
}
</style>
</head>
<body>
<!-- Minimal UI Annotations -->
<div class="ui-panel ui-top-left">
<div class="ui-title">最终理想解 (IFR) · 止流自适应机构</div>
<div class="ui-desc">
采用 TRIZ 思想剥离对外部电源与弱电控制的依赖。以现场气源为动力,利用流体势能(浮力)作为唯一感知输入。<br><br>
机械连杆 1:2 放大浮球行程,直接驱动 <span>气控换向阀</span> 抬升筛面并联动堰板减流。缓冲罐满载时,纯机械联动开启底端泄流阀。全过程 0 电子元件。
</div>
</div>
<!-- Interactive Controls -->
<div class="controls-container">
<button class="play-btn" id="playBtn" title="Play/Pause">
<!-- Pause Icon Default -->
<svg id="icon-pause" viewBox="0 0 24 24"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
<svg id="icon-play" viewBox="0 0 24 24" style="display:none;"><path d="M8 5v14l11-7z"/></svg>
</button>
<div class="slider-wrapper">
<span class="slider-label">CYCLE</span>
<input type="range" id="timeline" min="0" max="100" value="0" step="0.1">
<span class="slider-label" id="phase-label">0%</span>
</div>
</div>
<!-- Main SVG Animation Stage -->
<svg class="main-stage" viewBox="0 0 1400 900" preserveAspectRatio="xMidYMid meet">
<!-- Definitions for grids and filters -->
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" class="grid-line" />
</pattern>
<linearGradient id="fluidGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#84cc16" stop-opacity="0.8"/>
<stop offset="100%" stop-color="#65a30d" stop-opacity="0.9"/>
</linearGradient>
<clipPath id="screenClip">
<rect x="310" y="310" width="380" height="70" rx="4" />
</clipPath>
<clipPath id="tankClip">
<rect x="750" y="550" width="260" height="200" rx="8" />
</clipPath>
<filter id="neonAir" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- Background Grid -->
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- STATIC BACKGROUND ELEMENTS -->
<g id="static-layer">
<!-- Inlet Pipe -->
<path d="M220,-10 L220,180 L280,180 L280,-10" class="component" />
<!-- Main Pivot Base -->
<path d="M720,400 L740,450 L700,450 Z" class="component-dark" />
<!-- Air Supply Point -->
<rect x="80" y="550" width="60" height="30" rx="4" class="component-dark" />
<text x="110" y="570" class="blueprint-text" fill="#f8fafc" text-anchor="middle">0.7MPa气源</text>
<!-- Buffer Tank Outline -->
<rect x="750" y="550" width="260" height="200" rx="8" class="component" />
<path d="M1010,700 L1070,700 L1070,740 L1010,740 Z" class="component" /> <!-- Drain Pipe -->
<!-- Wire Rope Pulleys -->
<circle cx="290" cy="100" r="10" class="component-dark" />
<circle cx="260" cy="100" r="10" class="component-dark" />
</g>
<!-- DYNAMIC ELEMENTS (Controlled by JS) -->
<g id="dynamic-layer">
<!-- Inflow Fluid -->
<path id="inlet-fluid" d="M230,180 L270,180 L270,320 L230,320 Z" fill="url(#fluidGrad)" class="glow" />
<!-- Weir Plate (Slides Y) -->
<rect id="weir-plate" x="275" y="100" width="10" height="90" rx="2" class="component" fill="#cbd5e1" />
<!-- Dump Fluid (Screen to Tank) -->
<path id="dump-fluid" d="M710,380 Q760,380 770,550 L790,550 Q780,390 710,390 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
<!-- Drain Fluid (Tank Out) -->
<path id="drain-fluid" d="M1040,740 L1070,740 L1070,850 L1040,850 Z" fill="url(#fluidGrad)" opacity="0" class="glow" />
<!-- SCREEN GROUP (Rotates around Pivot 720, 390) -->
<g id="screen-group" transform="rotate(0, 720, 390)">
<!-- Screen Box -->
<rect x="300" y="300" width="420" height="90" rx="6" class="component" />
<line x1="310" y1="380" x2="710" y2="380" stroke="#334155" stroke-width="4" stroke-dasharray="8 4" /> <!-- Screen mesh -->
<!-- Screen Liquid -->
<g clip-path="url(#screenClip)">
<rect id="screen-liquid" x="310" y="380" width="380" height="0" fill="url(#fluidGrad)" class="glow" />
</g>
<!-- Float 1 & Internal Linkage -->
<circle id="float1" cx="380" cy="380" r="16" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
<!-- Lever connected to float1 -->
<line id="lever1" x1="380" y1="380" x2="460" y2="250" class="mechanical-link" />
<circle cx="430" cy="300" r="4" class="pivot" /> <!-- Pivot for Lever 1 -->
</g>
<circle cx="720" cy="390" r="8" class="pivot" /> <!-- Main Screen Pivot -->
<!-- PNEUMATIC SYSTEM -->
<!-- Air Valve -->
<rect x="440" y="230" width="40" height="40" rx="4" class="component-dark" />
<text x="460" y="215" class="blueprint-text" text-anchor="middle">气控换向阀</text>
<!-- Air Lines -->
<path id="air-line-in" d="M140,565 L180,565 L180,250 L440,250" class="air-line" />
<path id="air-line-out" d="M480,250 L520,250 L520,620 L330,620 L330,580" class="air-line" />
<!-- Pneumatic Cylinder -->
<rect x="290" y="480" width="40" height="100" rx="4" class="component-dark" />
<rect id="cylinder-rod" x="302" y="380" width="16" height="100" class="component" fill="#f8fafc" />
<circle id="cylinder-pin" cx="310" cy="380" r="5" class="pivot" />
<text x="260" y="530" class="blueprint-text" text-anchor="end">升降气缸</text>
<!-- Wire Rope Mechanism (Linked to Cylinder Rod) -->
<path id="wire-rope" d="M310,380 L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,100" class="wire-rope" />
<!-- BUFFER TANK SYSTEM -->
<!-- Tank Liquid -->
<g clip-path="url(#tankClip)">
<rect id="tank-liquid" x="750" y="750" width="260" height="0" fill="url(#fluidGrad)" class="glow" />
</g>
<!-- Float 2 & Butterfly Valve Linkage -->
<circle id="float2" cx="820" cy="730" r="20" fill="#facc15" stroke="#ca8a04" stroke-width="2" />
<line id="lever2" x1="820" y1="730" x2="1040" y2="650" class="mechanical-link" />
<circle cx="950" cy="682" r="5" class="pivot" /> <!-- Pivot for Lever 2 -->
<!-- Butterfly Valve Assembly -->
<circle cx="1040" cy="720" r="24" class="component-dark" />
<line id="valve-disc" x1="1040" y1="696" x2="1040" y2="744" stroke="#94a3b8" stroke-width="6" stroke-linecap="round" />
<text x="1100" y="725" class="blueprint-text highlight-text">纯机械联动蝶阀</text>
</g>
<!-- STATIC FOREGROUND ANNOTATIONS -->
<g id="annotations">
<!-- Screen Lift annotation -->
<line x1="160" y1="390" x2="280" y2="390" class="grid-line" stroke-dasharray="4" />
<path d="M220,390 L220,330" stroke="var(--text-muted)" stroke-width="1" marker-end="url(#arrow)" />
<text x="210" y="360" class="blueprint-text" text-anchor="end">抬升 100mm</text>
<!-- Float action annotation -->
<path d="M420,430 L380,430 L380,396" stroke="var(--text-muted)" stroke-width="1" fill="none" />
<text x="430" y="434" class="blueprint-text">液位行程 250mm</text>
<!-- Mechanical Ratio -->
<text x="430" y="280" class="blueprint-text">放大比 1:2</text>
<text x="880" y="660" class="blueprint-text">放大比联动</text>
</g>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--text-muted)" />
</marker>
</defs>
</svg>
<script>
/**
* Animation Math & Logic
* Driven by a 0-100 master timeline loop
*/
const state = {
t: 0,
playing: true,
speed: 0.15
};
// DOM Elements
const els = {
inlet_fluid: document.getElementById('inlet-fluid'),
weir_plate: document.getElementById('weir-plate'),
screen_group: document.getElementById('screen-group'),
screen_liquid: document.getElementById('screen-liquid'),
float1: document.getElementById('float1'),
lever1: document.getElementById('lever1'),
air_line_in: document.getElementById('air-line-in'),
air_line_out: document.getElementById('air-line-out'),
cylinder_rod: document.getElementById('cylinder-rod'),
cylinder_pin: document.getElementById('cylinder-pin'),
wire_rope: document.getElementById('wire-rope'),
dump_fluid: document.getElementById('dump-fluid'),
tank_liquid: document.getElementById('tank-liquid'),
float2: document.getElementById('float2'),
lever2: document.getElementById('lever2'),
valve_disc: document.getElementById('valve-disc'),
drain_fluid: document.getElementById('drain-fluid'),
timeline: document.getElementById('timeline'),
phase_label: document.getElementById('phase-label'),
play_btn: document.getElementById('playBtn'),
icon_play: document.getElementById('icon-play'),
icon_pause: document.getElementById('icon-pause')
};
// Easing functions for mechanical realism
function easeInOutQuad(x) {
return x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2;
}
// Map a time segment to a 0-1 value
function mapTime(t, start, end) {
if (t <= start) return 0;
if (t >= end) return 1;
return easeInOutQuad((t - start) / (end - start));
}
function updateFrame() {
let t = state.t; // 0 to 100
// 1. Inflow fills screen (0-20), then drains (40-60)
let L1_fill = mapTime(t, 0, 20);
let L1_drain = mapTime(t, 40, 60);
let L1 = L1_fill - L1_drain; // 0.0 to 1.0
// 2. Float 1 directly follows L1 mechanically
let F1 = L1;
// 3. Pneumatic Valve triggers when F1 > 0.8.
// Cylinder actuates (20-35), drops (75-90)
let airOn = (t > 18 && t < 78);
let C1_up = mapTime(t, 20, 35);
let C1_down = mapTime(t, 75, 90);
let C1 = C1_up - C1_down; // 0.0 to 1.0
// 4. Fluid flow from screen to tank happens when screen is lifted
let dump_active = (t > 38 && t < 65);
// 5. Tank fills (40-65), drains (65-85)
let L2_fill = mapTime(t, 40, 65);
let L2_drain = mapTime(t, 65, 85);
let L2 = L2_fill - L2_drain; // 0.0 to 1.0
// 6. Tank Float directly follows L2
let F2 = L2;
// 7. Valve Disc linked to F2
let V1 = F2;
// --- DOM UPDATES ---
// Screen Liquid Height (Max 65px)
let liquidH = L1 * 65;
els.screen_liquid.setAttribute('y', 380 - liquidH);
els.screen_liquid.setAttribute('height', liquidH);
// Screen Float 1 (Moves up with liquid)
let f1_y = 364 - liquidH;
els.float1.setAttribute('cy', f1_y);
// Lever 1 Rotation based on F1
let lever1_angle = -F1 * 25; // max 25 deg up
els.lever1.setAttribute('transform', `rotate(${lever1_angle}, 430, 300)`);
// Air Logic
if (airOn) {
els.air_line_in.classList.add('active');
els.air_line_out.classList.add('active');
} else {
els.air_line_in.classList.remove('active');
els.air_line_out.classList.remove('active');
}
// Cylinder Extends (Max 60px)
let cyl_ext = C1 * 60;
els.cylinder_rod.setAttribute('y', 380 - cyl_ext);
els.cylinder_rod.setAttribute('height', 100 + cyl_ext);
els.cylinder_pin.setAttribute('cy', 380 - cyl_ext);
// Screen Box Tilt (Max 12 deg)
let screen_angle = C1 * 12;
els.screen_group.setAttribute('transform', `rotate(${-screen_angle}, 720, 390)`);
// Weir Plate & Wire Rope (closes 50% = drops 45px)
let weir_drop = C1 * 45;
els.weir_plate.setAttribute('transform', `translate(0, ${weir_drop})`);
// Adjust Inlet fluid visual based on weir
if (weir_drop > 0) {
els.inlet_fluid.setAttribute('d', `M230,${180+weir_drop} L270,${180+weir_drop} L270,320 L230,320 Z`);
} else {
els.inlet_fluid.setAttribute('d', `M230,180 L270,180 L270,320 L230,320 Z`);
}
// Dynamic Wire Rope Path
els.wire_rope.setAttribute('d', `M310,${380 - cyl_ext} L310,100 M310,90 A10,10 0 0 0 290,90 M290,100 L290,110 M290,110 L260,110 M260,100 A10,10 0 0 0 280,100 M280,100 L280,${100 + weir_drop}`);
// Dump Fluid Appearance
els.dump_fluid.setAttribute('opacity', dump_active ? (C1 * 0.9) : 0);
// Tank Liquid Height (Max 150px)
let tank_liquidH = L2 * 150;
els.tank_liquid.setAttribute('y', 750 - tank_liquidH);
els.tank_liquid.setAttribute('height', tank_liquidH);
// Tank Float 2
let f2_y = 730 - tank_liquidH;
els.float2.setAttribute('cy', f2_y);
// Lever 2 Rotation (Pivot 950, 682)
let lever2_angle = -F2 * 35;
els.lever2.setAttribute('transform', `rotate(${lever2_angle}, 950, 682)`);
els.lever2.setAttribute('y1', f2_y);
// Butterfly Valve Disc Rotation (0 to 90deg)
let valve_angle = V1 * 90;
els.valve_disc.setAttribute('transform', `rotate(${valve_angle}, 1040, 720)`);
// Drain Fluid Appearance
els.drain_fluid.setAttribute('opacity', V1 > 0.1 ? V1 : 0);
// UI Updates
if (state.playing) {
els.timeline.value = t;
els.phase_label.innerText = Math.floor(t) + '%';
}
}
function loop() {
if (state.playing) {
state.t += state.speed;
if (state.t > 100) state.t = 0;
updateFrame();
}
requestAnimationFrame(loop);
}
// Interactivity
els.timeline.addEventListener('input', (e) => {
state.t = parseFloat(e.target.value);
els.phase_label.innerText = Math.floor(state.t) + '%';
updateFrame();
});
els.timeline.addEventListener('mousedown', () => { state.playing = false; updatePlayBtn(); });
els.timeline.addEventListener('mouseup', () => { state.playing = true; updatePlayBtn(); });
els.play_btn.addEventListener('click', () => {
state.playing = !state.playing;
updatePlayBtn();
});
function updatePlayBtn() {
if(state.playing) {
els.icon_pause.style.display = 'block';
els.icon_play.style.display = 'none';
} else {
els.icon_pause.style.display = 'none';
els.icon_play.style.display = 'block';
}
}
// Auto-start on load
window.addEventListener('DOMContentLoaded', () => {
state.t = 0;
state.playing = true;
updatePlayBtn();
loop();
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
