独立渲染引擎就绪引擎就绪
<!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: #0b1120;
--grid-color: rgba(255, 255, 255, 0.05);
--text-main: #f8fafc;
--text-muted: #94a3b8;
--accent-hot: #ff4713;
--accent-cold: #38bdf8;
--panel-bg: rgba(15, 23, 42, 0.7);
--panel-border: rgba(51, 65, 85, 0.6);
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: var(--bg-color);
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 30px 30px;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
color: var(--text-main);
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.container {
position: relative;
width: 100%;
max-width: 1200px;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-height: 85vh;
filter: drop-shadow(0 0 30px rgba(0,0,0,0.5));
}
/* 绝对定位的文本信息面板层,避免遮挡中心动画区域 */
.info-panel {
position: absolute;
background: var(--panel-bg);
border: 1px solid var(--panel-border);
padding: 16px 20px;
border-radius: 8px;
backdrop-filter: blur(8px);
font-size: 13px;
line-height: 1.6;
z-index: 10;
}
.panel-top-left { top: 30px; left: 40px; }
.panel-top-right { top: 30px; right: 40px; }
.panel-bottom-left { bottom: 30px; left: 40px; }
.panel-bottom-right { bottom: 30px; right: 40px; }
.title {
font-size: 18px;
font-weight: bold;
color: var(--text-main);
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.title::before {
content: '';
display: block;
width: 4px;
height: 16px;
background: var(--accent-hot);
border-radius: 2px;
}
.badge {
display: inline-block;
padding: 2px 8px;
border-radius: 12px;
font-size: 11px;
font-weight: bold;
background: rgba(255, 71, 19, 0.2);
color: var(--accent-hot);
border: 1px solid rgba(255, 71, 19, 0.4);
margin-bottom: 12px;
}
.data-row {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
gap: 20px;
}
.data-label { color: var(--text-muted); }
.status-indicator {
display: flex;
align-items: center;
gap: 6px;
font-size: 15px;
font-weight: bold;
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid var(--panel-border);
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: var(--accent-cold);
box-shadow: 0 0 8px var(--accent-cold);
transition: all 0.3s ease;
}
.note {
font-size: 11px;
color: #64748b;
margin-top: 8px;
font-style: italic;
}
/* Temp gauge styles */
.gauge-container {
display: flex;
align-items: center;
gap: 12px;
}
.gauge-bar {
width: 150px;
height: 6px;
background: #1e293b;
border-radius: 3px;
position: relative;
overflow: hidden;
}
.gauge-fill {
position: absolute;
left: 0; top: 0; bottom: 0;
width: 0%;
background: linear-gradient(90deg, var(--accent-cold), var(--accent-hot));
border-radius: 3px;
}
.temp-text {
font-size: 24px;
font-weight: bold;
color: var(--accent-cold);
min-width: 70px;
text-align: right;
font-variant-numeric: tabular-nums;
}
</style>
</head>
<body>
<div class="container">
<!-- 面板信息 -->
<div class="info-panel panel-top-left">
<div class="title">最终理想解 (IFR) 设计</div>
<div class="badge">TRIZ 理论应用</div>
<div class="data-row">
<span class="data-label">核心矛盾:</span>
<span>需避让肩台(小尺寸) vs 需抗剪锁定(大尺寸)</span>
</div>
<div class="data-row">
<span class="data-label">引入资源:</span>
<span style="color: var(--accent-hot)">系统自身热能 (150℃ -> 300℃)</span>
</div>
<div class="data-row">
<span class="data-label">理想解状态:</span>
<span>无额外活动部件,依靠环境温度自动形变锁紧</span>
</div>
</div>
<div class="info-panel panel-top-right">
<div class="title">运行参数监控</div>
<div class="gauge-container" style="margin: 15px 0;">
<div class="gauge-bar">
<div class="gauge-fill" id="gauge-fill"></div>
</div>
<div class="temp-text" id="temp-val">150℃</div>
</div>
<div class="status-indicator">
<div class="dot" id="status-dot"></div>
<span id="status-text" style="color: var(--accent-cold);">收拢状态 (自由装拔)</span>
</div>
</div>
<div class="info-panel panel-bottom-left">
<div class="title">结构参数</div>
<div class="data-row"><span class="data-label">部件构成:</span><span>6片双金属悬臂梁 (截面展示2片)</span></div>
<div class="data-row"><span class="data-label">高膨胀层:</span><span style="color: #ef4444;">内侧红橙色区域</span></div>
<div class="data-row"><span class="data-label">低膨胀层:</span><span style="color: #64748b;">外侧暗灰色区域</span></div>
<div class="data-row"><span class="data-label">形变位移:</span><span>≥ 3.0 mm (视觉放大)</span></div>
<div class="note">* 动画中横向位移特征已作适当视觉放大以清晰展示机理</div>
</div>
<div class="info-panel panel-bottom-right">
<div class="title">动作时序</div>
<div class="data-row" id="step-1" style="color: var(--accent-cold);">1. 150℃: 钩端收拢,无损拔插避让肩台</div>
<div class="data-row" id="step-2" style="color: #f59e0b; opacity: 0.5;">2. 升温过程: 双金属层膨胀差导致悬臂梁外翻</div>
<div class="data-row" id="step-3" style="color: var(--accent-hot); opacity: 0.5;">3. 300℃: 卡钩伸入肩台下方,形成抗剪锁紧</div>
</div>
<!-- 核心 SVG 动画区 -->
<svg viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 材质渐变定义 -->
<linearGradient id="metal-flange" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#475569" />
<stop offset="50%" stop-color="#334155" />
<stop offset="100%" stop-color="#1e293b" />
</linearGradient>
<linearGradient id="metal-shoulder" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<linearGradient id="metal-hook" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#94a3b8" />
<stop offset="100%" stop-color="#475569" />
</linearGradient>
<!-- 阴影带与纹理 -->
<pattern id="hatch" width="8" height="8" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="8" stroke="rgba(255,255,255,0.03)" stroke-width="2" />
</pattern>
<filter id="glow-hot" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- 静态背景基准线 -->
<line x1="400" y1="50" x2="400" y2="550" stroke="rgba(255,255,255,0.1)" stroke-width="1" stroke-dasharray="5 5" />
<text x="410" y="70" fill="rgba(255,255,255,0.3)" font-size="12">中心轴线 CL</text>
<!-- 固定支座环形肩台 (左侧) -->
<g id="left-shoulder">
<path d="M 50,280 L 290,280 L 290,410 L 50,410 Z" fill="url(#metal-shoulder)" stroke="#334155" stroke-width="2" />
<path d="M 50,280 L 290,280 L 290,410 L 50,410 Z" fill="url(#hatch)" />
<rect x="290" y="280" width="4" height="130" fill="#64748b" /> <!-- 边缘高光 -->
<text x="170" y="350" fill="rgba(255,255,255,0.2)" font-size="14" text-anchor="middle" letter-spacing="2">固定支座肩台</text>
</g>
<!-- 固定支座环形肩台 (右侧) -->
<g id="right-shoulder">
<path d="M 510,280 L 750,280 L 750,410 L 510,410 Z" fill="url(#metal-shoulder)" stroke="#334155" stroke-width="2" />
<path d="M 510,280 L 750,280 L 750,410 L 510,410 Z" fill="url(#hatch)" />
<rect x="506" y="280" width="4" height="130" fill="#64748b" /> <!-- 边缘高光 -->
<text x="630" y="350" fill="rgba(255,255,255,0.2)" font-size="14" text-anchor="middle" letter-spacing="2">固定支座肩台</text>
</g>
<!-- 顶部法兰 (随中心件固定) -->
<path d="M 220,100 L 580,100 L 580,160 L 220,160 Z" fill="url(#metal-flange)" stroke="#64748b" stroke-width="2" />
<circle cx="260" cy="130" r="6" fill="#0f172a" stroke="#64748b" stroke-width="2" />
<circle cx="330" cy="130" r="6" fill="#0f172a" stroke="#64748b" stroke-width="2" />
<circle cx="470" cy="130" r="6" fill="#0f172a" stroke="#64748b" stroke-width="2" />
<circle cx="540" cy="130" r="6" fill="#0f172a" stroke="#64748b" stroke-width="2" />
<text x="400" y="135" fill="rgba(255,255,255,0.5)" font-size="16" text-anchor="middle" font-weight="bold" letter-spacing="4">反射体底法兰</text>
<!-- 动态双金属悬臂梁 (左侧) -->
<g id="left-beam-group">
<!-- 低膨胀层 (外侧 - 灰) -->
<path id="left-outer" fill="#475569" stroke="#1e293b" stroke-width="1" />
<!-- 高膨胀层 发光背板 -->
<path id="left-inner-glow" fill="#ff4713" filter="url(#glow-hot)" opacity="0" />
<!-- 高膨胀层 (内侧 - 热敏) -->
<path id="left-inner" fill="#94a3b8" stroke="#1e293b" stroke-width="1" />
<!-- 刚性钩头 -->
<g id="left-hook-head">
<path d="M 0,0 L 0,28 L -38,28 L -38,13 L -16,13 L -16,0 Z" fill="url(#metal-hook)" stroke="#1e293b" stroke-width="1" stroke-linejoin="round" />
<!-- 耐磨堆焊层标识 -->
<path d="M -38,28 L -16,28 L -16,13 L -38,13 Z" fill="none" stroke="#fbbf24" stroke-width="2" opacity="0.6"/>
</g>
</g>
<!-- 动态双金属悬臂梁 (右侧) -->
<g id="right-beam-group">
<!-- 低膨胀层 (外侧 - 灰) -->
<path id="right-outer" fill="#475569" stroke="#1e293b" stroke-width="1" />
<!-- 高膨胀层 发光背板 -->
<path id="right-inner-glow" fill="#ff4713" filter="url(#glow-hot)" opacity="0" />
<!-- 高膨胀层 (内侧 - 热敏) -->
<path id="right-inner" fill="#94a3b8" stroke="#1e293b" stroke-width="1" />
<!-- 刚性钩头 -->
<g id="right-hook-head">
<path d="M 0,0 L 0,28 L 38,28 L 38,13 L 16,13 L 16,0 Z" fill="url(#metal-hook)" stroke="#1e293b" stroke-width="1" stroke-linejoin="round" />
<!-- 耐磨堆焊层标识 -->
<path d="M 38,28 L 16,28 L 16,13 L 38,13 Z" fill="none" stroke="#fbbf24" stroke-width="2" opacity="0.6"/>
</g>
</g>
<!-- 间隙与深度指示线 (动态透明度) -->
<g id="dimension-lines" opacity="0">
<line x1="264" y1="418" x2="290" y2="418" stroke="#ef4444" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)" />
<text x="277" y="435" fill="#ef4444" font-size="12" text-anchor="middle">5mm</text>
</g>
</svg>
</div>
<script>
// 核心参数设定
const FLANGE_Y = 160;
const HOOK_Y_BASE = 390;
const LEFT_BASE_X = 330;
const RIGHT_BASE_X = 470;
const BEAM_THICKNESS = 8; // 单层厚度
const MAX_BEND_OFFSET = 32; // 放大后的横向弯曲位移
const MAX_ANGLE = 14; // 底部钩头随动角度
// DOM 元素引用
const els = {
leftInner: document.getElementById('left-inner'),
leftOuter: document.getElementById('left-outer'),
leftInnerGlow: document.getElementById('left-inner-glow'),
leftHookHead: document.getElementById('left-hook-head'),
rightInner: document.getElementById('right-inner'),
rightOuter: document.getElementById('right-outer'),
rightInnerGlow: document.getElementById('right-inner-glow'),
rightHookHead: document.getElementById('right-hook-head'),
tempVal: document.getElementById('temp-val'),
gaugeFill: document.getElementById('gauge-fill'),
statusDot: document.getElementById('status-dot'),
statusText: document.getElementById('status-text'),
dimLines: document.getElementById('dimension-lines'),
step1: document.getElementById('step-1'),
step2: document.getElementById('step-2'),
step3: document.getElementById('step-3')
};
// 颜色插值函数 (150C -> 300C, 冷钢色 -> 炙热橙红)
function interpolateColor(t) {
// Cold: #94a3b8 (148, 163, 184)
// Hot: #ff4713 (255, 71, 19)
const r = Math.round(148 + (255 - 148) * t);
const g = Math.round(163 + (71 - 163) * t);
const b = Math.round(184 + (19 - 184) * t);
return `rgb(${r}, ${g}, ${b})`;
}
// 动画更新主逻辑 (t: 0.0 ~ 1.0)
function updateMechanism(t) {
const temp = Math.round(150 + 150 * t);
// 1. 更新 UI 面板
els.tempVal.textContent = `${temp}℃`;
els.gaugeFill.style.width = `${t * 100}%`;
if (t < 0.1) {
els.statusText.textContent = "收拢状态 (避让间隙 > 2mm)";
els.statusText.style.color = "var(--accent-cold)";
els.statusDot.style.backgroundColor = "var(--accent-cold)";
els.statusDot.style.boxShadow = "0 0 8px var(--accent-cold)";
els.dimLines.setAttribute('opacity', '0');
els.step1.style.opacity = '1';
els.step2.style.opacity = '0.4';
els.step3.style.opacity = '0.4';
} else if (t > 0.9) {
els.statusText.textContent = "锁定状态 (抗剪钩入深度 5mm)";
els.statusText.style.color = "var(--accent-hot)";
els.statusDot.style.backgroundColor = "var(--accent-hot)";
els.statusDot.style.boxShadow = "0 0 12px var(--accent-hot)";
els.dimLines.setAttribute('opacity', '1');
els.step1.style.opacity = '0.4';
els.step2.style.opacity = '0.4';
els.step3.style.opacity = '1';
} else {
els.statusText.textContent = "环境升温,自适应热变形驱动中...";
els.statusText.style.color = "#f59e0b";
els.statusDot.style.backgroundColor = "#f59e0b";
els.statusDot.style.boxShadow = "0 0 8px #f59e0b";
els.dimLines.setAttribute('opacity', t.toString());
els.step1.style.opacity = '0.4';
els.step2.style.opacity = '1';
els.step3.style.opacity = '0.4';
}
// 2. 计算结构变形学参数
// 左侧向左弯曲 (负向X位移),右侧向右弯曲 (正向X位移)
const bendOffset = MAX_BEND_OFFSET * t;
const bendAngle = MAX_ANGLE * t;
// 左侧坐标系计算
const lEndX = LEFT_BASE_X - bendOffset;
const lCtrlX = LEFT_BASE_X - bendOffset * 0.45; // 贝塞尔控制点,营造悬臂梁弯曲感
// 高膨胀层 (左悬臂梁内侧,靠右的一层)
const lInnerPath = `M ${LEFT_BASE_X} ${FLANGE_Y}
Q ${lCtrlX} 270 ${lEndX} ${HOOK_Y_BASE}
L ${lEndX - BEAM_THICKNESS} ${HOOK_Y_BASE}
Q ${lCtrlX - BEAM_THICKNESS} 270 ${LEFT_BASE_X - BEAM_THICKNESS} ${FLANGE_Y} Z`;
// 低膨胀层 (左悬臂梁外侧,靠左的一层)
const lOuterPath = `M ${LEFT_BASE_X - BEAM_THICKNESS} ${FLANGE_Y}
Q ${lCtrlX - BEAM_THICKNESS} 270 ${lEndX - BEAM_THICKNESS} ${HOOK_Y_BASE}
L ${lEndX - BEAM_THICKNESS*2} ${HOOK_Y_BASE}
Q ${lCtrlX - BEAM_THICKNESS*2} 270 ${LEFT_BASE_X - BEAM_THICKNESS*2} ${FLANGE_Y} Z`;
// 右侧坐标系计算
const rEndX = RIGHT_BASE_X + bendOffset;
const rCtrlX = RIGHT_BASE_X + bendOffset * 0.45;
// 高膨胀层 (右悬臂梁内侧,靠左的一层)
const rInnerPath = `M ${RIGHT_BASE_X} ${FLANGE_Y}
Q ${rCtrlX} 270 ${rEndX} ${HOOK_Y_BASE}
L ${rEndX + BEAM_THICKNESS} ${HOOK_Y_BASE}
Q ${rCtrlX + BEAM_THICKNESS} 270 ${RIGHT_BASE_X + BEAM_THICKNESS} ${FLANGE_Y} Z`;
// 低膨胀层 (右悬臂梁外侧,靠右的一层)
const rOuterPath = `M ${RIGHT_BASE_X + BEAM_THICKNESS} ${FLANGE_Y}
Q ${rCtrlX + BEAM_THICKNESS} 270 ${rEndX + BEAM_THICKNESS} ${HOOK_Y_BASE}
L ${rEndX + BEAM_THICKNESS*2} ${HOOK_Y_BASE}
Q ${rCtrlX + BEAM_THICKNESS*2} 270 ${RIGHT_BASE_X + BEAM_THICKNESS*2} ${FLANGE_Y} Z`;
// 3. 应用路径与变换
els.leftInner.setAttribute('d', lInnerPath);
els.leftInnerGlow.setAttribute('d', lInnerPath);
els.leftOuter.setAttribute('d', lOuterPath);
els.leftHookHead.setAttribute('transform', `translate(${lEndX}, ${HOOK_Y_BASE}) rotate(${bendAngle})`);
els.rightInner.setAttribute('d', rInnerPath);
els.rightInnerGlow.setAttribute('d', rInnerPath);
els.rightOuter.setAttribute('d', rOuterPath);
els.rightHookHead.setAttribute('transform', `translate(${rEndX}, ${HOOK_Y_BASE}) rotate(${-bendAngle})`);
// 4. 应用颜色与发光特效
const heatColor = interpolateColor(t);
els.leftInner.setAttribute('fill', heatColor);
els.rightInner.setAttribute('fill', heatColor);
// 发光层透明度与温度强相关
const glowOpacity = Math.max(0, (t - 0.2) * 1.25);
els.leftInnerGlow.setAttribute('opacity', glowOpacity.toString());
els.rightInnerGlow.setAttribute('opacity', glowOpacity.toString());
}
// 动画时间轴控制
let startTime = null;
const CYCLE_DURATION = 10000; // 完整的循环周期:10秒
function animationLoop(timestamp) {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
const phase = (elapsed % CYCLE_DURATION) / CYCLE_DURATION;
let t = 0;
// 阶段切分:
// 0.0 - 0.1: 保持 150℃ (t=0)
// 0.1 - 0.4: 升温至 300℃ (t 0->1)
// 0.4 - 0.6: 保持 300℃ (t=1)
// 0.6 - 0.9: 降温至 150℃ (t 1->0)
// 0.9 - 1.0: 保持 150℃ (t=0)
if (phase < 0.1) {
t = 0;
} else if (phase < 0.4) {
// 平滑缓动升温
const progress = (phase - 0.1) / 0.3;
t = 0.5 - Math.cos(progress * Math.PI) / 2;
} else if (phase < 0.6) {
t = 1;
} else if (phase < 0.9) {
// 平滑缓动降温
const progress = (phase - 0.6) / 0.3;
t = 0.5 + Math.cos(progress * Math.PI) / 2;
} else {
t = 0;
}
updateMechanism(t);
requestAnimationFrame(animationLoop);
}
// 页面加载完成后自动触发动画,重开即播
window.addEventListener('DOMContentLoaded', () => {
requestAnimationFrame(animationLoop);
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
