独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高膨胀推杆正锁合结构原理演示 - TRIZ IFR</title>
<style>
:root {
--bg-color: #050914;
--grid-color: rgba(30, 41, 59, 0.5);
--text-main: #94A3B8;
--text-highlight: #38BDF8;
--text-alert: #F87171;
--part-fixed: #0F172A;
--part-stroke: #334155;
--accent-cold: #3B82F6;
--accent-hot: #EF4444;
--block-color: #F59E0B;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: 'JetBrains Mono', 'Courier New', Consolas, monospace;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
overflow: hidden;
}
.canvas-container {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 900px;
filter: drop-shadow(0 0 20px rgba(0, 0, 0, 0.5));
}
text {
user-select: none;
}
.hud-title {
font-size: 16px;
font-weight: bold;
fill: #F8FAFC;
letter-spacing: 1px;
}
.hud-text {
font-size: 12px;
fill: #94A3B8;
}
.hud-value {
font-size: 13px;
font-weight: bold;
fill: var(--text-highlight);
font-variant-numeric: tabular-nums;
}
.hud-panel {
fill: rgba(15, 23, 42, 0.8);
stroke: var(--part-stroke);
stroke-width: 1;
rx: 6;
}
.axis-line {
stroke: rgba(148, 163, 184, 0.2);
stroke-dasharray: 4 4;
stroke-width: 1;
}
</style>
</head>
<body>
<div class="canvas-container">
<svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet" id="mainSvg">
<!-- Definitions -->
<defs>
<!-- Blueprint Grid -->
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="var(--grid-color)" stroke-width="0.5"/>
</pattern>
<!-- Mechanical Hatching for Fixed Parts -->
<pattern id="hatch" width="10" height="10" patternUnits="userSpaceOnUse">
<rect width="10" height="10" fill="var(--part-fixed)" />
<path d="M-2,12 L12,-2" stroke="#1E293B" stroke-width="1.5" />
</pattern>
<!-- Inner Guide Fill -->
<pattern id="hatch-guide" width="8" height="8" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<rect width="8" height="8" fill="#172033" />
<line x1="0" y1="0" x2="0" y2="8" stroke="#28354D" stroke-width="1" />
</pattern>
<!-- Glow Filters -->
<filter id="glow-hot" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Gradients -->
<linearGradient id="rod-grad-cold" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1E293B" />
<stop offset="20%" stop-color="#475569" />
<stop offset="50%" stop-color="#94A3B8" />
<stop offset="80%" stop-color="#475569" />
<stop offset="100%" stop-color="#1E293B" />
</linearGradient>
<linearGradient id="rod-grad-hot" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#7F1D1D" />
<stop offset="20%" stop-color="#B91C1C" />
<stop offset="50%" stop-color="#FCA5A5" />
<stop offset="80%" stop-color="#B91C1C" />
<stop offset="100%" stop-color="#7F1D1D" />
</linearGradient>
<linearGradient id="block-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#F59E0B" />
<stop offset="50%" stop-color="#FCD34D" />
<stop offset="100%" stop-color="#D97706" />
</linearGradient>
</defs>
<!-- Background Grid -->
<rect width="1000" height="700" fill="url(#grid)" />
<!-- Centerline -->
<line x1="500" y1="50" x2="500" y2="650" stroke="#64748B" stroke-dasharray="15 5 5 5" stroke-width="1" opacity="0.5" />
<line x1="150" y1="510" x2="850" y2="510" stroke="#64748B" stroke-dasharray="15 5 5 5" stroke-width="1" opacity="0.3" />
<!-- ================= MECHANISM ================= -->
<g id="mechanismGroup">
<!-- 1. FIXED OUTER SUPPORTS (支座) -->
<!-- Left Fixed Support -->
<path d="M 150,100 L 340,100 L 340,485 L 300,485 L 300,535 L 340,535 L 340,650 L 150,650 Z"
fill="url(#hatch)" stroke="var(--accent-cold)" stroke-width="1.5" />
<!-- Right Fixed Support -->
<path d="M 850,100 L 660,100 L 660,485 L 700,485 L 700,535 L 660,535 L 660,650 L 850,650 Z"
fill="url(#hatch)" stroke="var(--accent-cold)" stroke-width="1.5" />
<!-- 2. INNER GUIDES (导向槽法兰) -->
<!-- Left Top Guide -->
<path d="M 340,100 L 435,100 L 435,485 L 340,485 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
<!-- Left Bottom Guide -->
<path d="M 340,550 L 435,550 L 435,650 L 340,650 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
<!-- Right Top Guide -->
<path d="M 660,100 L 565,100 L 565,485 L 660,485 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
<!-- Right Bottom Guide -->
<path d="M 660,550 L 565,550 L 565,650 L 660,650 Z" fill="url(#hatch-guide)" stroke="#475569" stroke-width="1" />
<!-- 3. PUSH ROD (高膨胀推杆 - Moves Vertically) -->
<g id="pushRod" transform="translate(0, 0)">
<!-- Cold State Body -->
<rect x="440" y="0" width="120" height="600" fill="url(#rod-grad-cold)" stroke="#64748B" stroke-width="1.5" id="rodBodyCold"/>
<!-- Hot State Body (Opacity controlled by JS) -->
<rect x="440" y="0" width="120" height="600" fill="url(#rod-grad-hot)" stroke="#FCA5A5" stroke-width="2" id="rodBodyHot" opacity="0" filter="url(#glow-hot)"/>
<!-- Left Slanted Slot (Cutout illusion) -->
<!-- Slot trajectory: x1=440, y1=480 to x2=500, y2=540 -->
<path d="M 438,478 L 442,478 L 502,538 L 498,538 Z" fill="#020617" opacity="0.8" />
<line x1="440" y1="480" x2="500" y2="540" stroke="#0B101E" stroke-width="14" stroke-linecap="round" />
<line x1="440" y1="480" x2="500" y2="540" stroke="#1E293B" stroke-width="12" stroke-linecap="round" />
<!-- Right Slanted Slot -->
<path d="M 562,478 L 558,478 L 498,538 L 502,538 Z" fill="#020617" opacity="0.8" />
<line x1="560" y1="480" x2="500" y2="540" stroke="#0B101E" stroke-width="14" stroke-linecap="round" />
<line x1="560" y1="480" x2="500" y2="540" stroke="#1E293B" stroke-width="12" stroke-linecap="round" />
<!-- 12° Angle Annotation -->
<g stroke="#94A3B8" stroke-width="1" fill="none" opacity="0.8">
<line x1="440" y1="480" x2="440" y2="540" stroke-dasharray="2 2" />
<path d="M 440,510 A 30 30 0 0 0 470,510" stroke-dasharray="2 2"/>
<text x="445" y="525" class="hud-text" fill="#94A3B8" stroke="none">12°</text>
</g>
</g>
<!-- 4. SPRINGS (回位弹簧 - Paths updated by JS) -->
<path id="springLeft" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linejoin="round" />
<path id="springRight" fill="none" stroke="#94A3B8" stroke-width="2" stroke-linejoin="round" />
<!-- 5. LOCK BLOCKS (径向锁块 - Moves Horizontally) -->
<!-- Left Block Group -->
<g id="blockLeft" transform="translate(0, 0)">
<!-- Main Block -->
<path d="M 370,485 L 470,485 L 470,535 L 370,535 Z" fill="url(#block-grad)" stroke="#B45309" stroke-width="1.5" />
<!-- Spring Anchor Tab -->
<path d="M 400,535 L 420,535 L 420,550 L 400,550 Z" fill="#92400E" stroke="#78350F" stroke-width="1" />
<circle cx="410" cy="542.5" r="2.5" fill="#CBD5E1" />
<!-- Drive Pin (Roller) -->
<circle cx="470" cy="510" r="7" fill="#E2E8F0" stroke="#475569" stroke-width="2" />
<circle cx="470" cy="510" r="3" fill="#64748B" />
<!-- Motion Indicator Arrows -->
<path id="arrowLeft" d="M 350,510 L 360,505 L 360,515 Z" fill="#F87171" opacity="0" />
</g>
<!-- Right Block Group -->
<g id="blockRight" transform="translate(0, 0)">
<!-- Main Block -->
<path d="M 630,485 L 530,485 L 530,535 L 630,535 Z" fill="url(#block-grad)" stroke="#B45309" stroke-width="1.5" />
<!-- Spring Anchor Tab -->
<path d="M 600,535 L 580,535 L 580,550 L 600,550 Z" fill="#92400E" stroke="#78350F" stroke-width="1" />
<circle cx="590" cy="542.5" r="2.5" fill="#CBD5E1" />
<!-- Drive Pin (Roller) -->
<circle cx="530" cy="510" r="7" fill="#E2E8F0" stroke="#475569" stroke-width="2" />
<circle cx="530" cy="510" r="3" fill="#64748B" />
<!-- Motion Indicator Arrows -->
<path id="arrowRight" d="M 650,510 L 640,505 L 640,515 Z" fill="#F87171" opacity="0" />
</g>
<!-- Fixed Spring Anchors on Guide -->
<path d="M 430,535 L 440,535 L 440,550 L 430,550 Z" fill="#1E293B" stroke="#0F172A" />
<circle cx="435" cy="542.5" r="2.5" fill="#64748B" />
<path d="M 570,535 L 560,535 L 560,550 L 570,550 Z" fill="#1E293B" stroke="#0F172A" />
<circle cx="565" cy="542.5" r="2.5" fill="#64748B" />
</g>
<!-- ================= HUD & ANNOTATIONS ================= -->
<!-- Top Left Status HUD -->
<g transform="translate(30, 30)">
<rect width="240" height="130" class="hud-panel" />
<text x="15" y="25" class="hud-title">SYSTEM STATUS</text>
<line x1="15" y1="35" x2="225" y2="35" stroke="var(--part-stroke)" stroke-width="1" />
<text x="15" y="55" class="hud-text">系统温度 (TEMP):</text>
<text x="160" y="55" class="hud-value" id="valTemp">150.0 ℃</text>
<text x="15" y="75" class="hud-text">推杆轴向位移 (ΔY):</text>
<text x="160" y="75" class="hud-value" id="valRodY">0.00 mm</text>
<text x="15" y="95" class="hud-text">锁块径向伸出 (ΔX):</text>
<text x="160" y="95" class="hud-value" id="valBlockX">0.00 mm</text>
<text x="15" y="115" class="hud-text">锁合状态 (LOCK):</text>
<text x="160" y="115" class="hud-value" id="valStatus" fill="#34D399">UNLOCKED</text>
</g>
<!-- Top Right TRIZ IFR HUD -->
<g transform="translate(680, 30)">
<rect width="290" height="110" class="hud-panel" />
<text x="15" y="25" class="hud-title" fill="#FBBF24">TRIZ 最终理想解 (IFR)</text>
<line x1="15" y1="35" x2="275" y2="35" stroke="var(--part-stroke)" stroke-width="1" />
<text x="15" y="55" class="hud-text" fill="#E2E8F0">核心矛盾消除:承载力 vs 系统复杂度</text>
<text x="15" y="75" class="hud-text">利用系统固有的<tspan fill="#FCA5A5">【温差热能】</tspan>作为驱动源</text>
<text x="15" y="95" class="hud-text">无须外部动力,实现绝对可靠的自动正锁合</text>
</g>
<!-- Mechanism Labels (Static) -->
<g class="hud-text">
<!-- Rod Label -->
<line x1="500" y1="200" x2="600" y2="150" stroke="#94A3B8" stroke-width="1" />
<text x="605" y="148">高膨胀镍基合金推杆</text>
<text x="605" y="163" font-size="10" fill="#64748B">CTE ≈ 17×10⁻⁶/℃</text>
<!-- Annular Groove Label -->
<line x1="300" y1="510" x2="210" y2="450" stroke="#94A3B8" stroke-width="1" />
<text x="120" y="445">固定支座环形锁槽</text>
<!-- Lock Block Label -->
<line x1="390" y1="490" x2="310" y2="410" stroke="#94A3B8" stroke-width="1" />
<text x="260" y="405">径向正锁合锁块</text>
<!-- Spring Label -->
<line x1="430" y1="550" x2="350" y2="590" stroke="#94A3B8" stroke-width="1" />
<text x="300" y="605">强力回位弹簧</text>
<!-- Slope Extender Label -->
<line x1="520" y1="510" x2="600" y2="570" stroke="#94A3B8" stroke-width="1" />
<text x="605" y="575">12° 斜槽 (运动行程放大)</text>
</g>
</svg>
</div>
<script>
// Elements
const rodCold = document.getElementById('rodBodyCold');
const rodHot = document.getElementById('rodBodyHot');
const pushRod = document.getElementById('pushRod');
const blockLeft = document.getElementById('blockLeft');
const blockRight = document.getElementById('blockRight');
const springLeft = document.getElementById('springLeft');
const springRight = document.getElementById('springRight');
const arrowLeft = document.getElementById('arrowLeft');
const arrowRight = document.getElementById('arrowRight');
// HUD Elements
const valTemp = document.getElementById('valTemp');
const valRodY = document.getElementById('valRodY');
const valBlockX = document.getElementById('valBlockX');
const valStatus = document.getElementById('valStatus');
// Animation Constants
const CYCLE_DURATION = 12000; // Total ms per cycle
const MAX_ROD_Y = 60; // visual px
const MAX_BLOCK_X = 60; // visual px
const MAX_TEMP = 300;
const MIN_TEMP = 150;
// Physics / Engineering mapped constants for HUD
const REAL_MAX_ROD_MM = 0.77;
const REAL_MAX_BLOCK_MM = 3.60;
// Easing function (Smooth sine wave style acceleration/deceleration)
function easeInOutCubic(x) {
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
}
// Spring Drawing Generator (Draws a realistic zigzag spring)
function drawSpringPath(x1, x2, y, coils, amplitude) {
let path = `M ${x1},${y} `;
const dir = x2 > x1 ? 1 : -1;
const totalW = Math.abs(x2 - x1);
const startPad = 5;
path += `L ${x1 + dir * startPad},${y} `;
const workingW = totalW - startPad * 2;
const step = workingW / coils;
let currentX = x1 + dir * startPad;
for (let i = 0; i < coils; i++) {
path += `L ${currentX + dir * (step * 0.25)},${y - amplitude} `;
path += `L ${currentX + dir * (step * 0.75)},${y + amplitude} `;
path += `L ${currentX + dir * step},${y} `;
currentX += dir * step;
}
path += `L ${x2},${y}`;
return path;
}
// Main animation loop
function animate(timestamp) {
const timeInCycle = timestamp % CYCLE_DURATION;
let progress = 0; // 0 to 1
// Define cycle phases
// 0-15%: Idle Cool (150)
// 15-40%: Heating up
// 40-65%: Hold Hot (300) -> Locked State
// 65-90%: Cooling down
// 90-100%: Idle Cool (150)
const pHeatStart = 0.15, pHeatEnd = 0.40;
const pCoolStart = 0.65, pCoolEnd = 0.90;
const normTime = timeInCycle / CYCLE_DURATION;
if (normTime < pHeatStart) {
progress = 0;
} else if (normTime < pHeatEnd) {
const t = (normTime - pHeatStart) / (pHeatEnd - pHeatStart);
progress = easeInOutCubic(t);
} else if (normTime < pCoolStart) {
progress = 1;
} else if (normTime < pCoolEnd) {
const t = (normTime - pCoolStart) / (pCoolEnd - pCoolStart);
progress = 1 - easeInOutCubic(t);
} else {
progress = 0;
}
// 1. Update Transforms
const currentRodY = MAX_ROD_Y * progress;
const currentBlockX = MAX_BLOCK_X * progress;
pushRod.setAttribute('transform', `translate(0, ${currentRodY})`);
blockLeft.setAttribute('transform', `translate(${-currentBlockX}, 0)`);
blockRight.setAttribute('transform', `translate(${currentBlockX}, 0)`);
// 2. Update Springs
// Left Spring: fixed anchor at x=435, tab moves from 410 down to 350
const leftTabX = 410 - currentBlockX;
springLeft.setAttribute('d', drawSpringPath(435, leftTabX, 542.5, 6, 4));
// Right Spring: fixed anchor at x=565, tab moves from 590 up to 650
const rightTabX = 590 + currentBlockX;
springRight.setAttribute('d', drawSpringPath(565, rightTabX, 542.5, 6, 4));
// 3. Visual FX (Heat Glow)
rodHot.setAttribute('opacity', progress.toFixed(2));
// Motion arrows
const isMovingOut = normTime > pHeatStart && normTime < pHeatEnd;
arrowLeft.setAttribute('opacity', isMovingOut ? '1' : '0');
arrowRight.setAttribute('opacity', isMovingOut ? '1' : '0');
// 4. Update HUD Data
const currentTemp = MIN_TEMP + (MAX_TEMP - MIN_TEMP) * progress;
valTemp.textContent = `${currentTemp.toFixed(1)} ℃`;
// Color mapping for temperature text
if (progress > 0.8) valTemp.setAttribute('fill', '#FCA5A5');
else if (progress > 0.3) valTemp.setAttribute('fill', '#FCD34D');
else valTemp.setAttribute('fill', '#38BDF8');
valRodY.textContent = `${(REAL_MAX_ROD_MM * progress).toFixed(2)} mm`;
valBlockX.textContent = `${(REAL_MAX_BLOCK_MM * progress).toFixed(2)} mm`;
if (progress > 0.95) {
valStatus.textContent = "正锁合 (LOCKED)";
valStatus.setAttribute('fill', '#EF4444');
} else if (progress < 0.05) {
valStatus.textContent = "释放 (UNLOCKED)";
valStatus.setAttribute('fill', '#34D399');
} else {
valStatus.textContent = "动作中 (TRANSITION)";
valStatus.setAttribute('fill', '#FBBF24');
}
requestAnimationFrame(animate);
}
// Start animation loop immediately
requestAnimationFrame(animate);
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
