独立渲染引擎就绪引擎就绪
以下是为您设计的高保真 SVG 交互式原理动画。
该设计采用了工业蓝图与赛博朋克融合的暗色高保真美学 (Cyber-Blueprint Aesthetics),以极致的视觉对比度和精确的机械运动,直观展现 TRIZ 中“最终理想解 (IFR)”的破除矛盾过程。动画会在页面加载后自动循环播放,您也可以通过底部滑块进行手动微调。
<!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>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Noto+Sans+SC:wght@400;700&display=swap');
:root {
--bg-color: #060b13;
--grid-color: rgba(56, 189, 248, 0.05);
--hub-color: #111827;
--hub-stroke: #334155;
--shaft-color: #0f172a;
--shaft-stroke: #475569;
--inner-cone: #ff7e67;
--outer-cone: #00f0ff;
--bolt-color: #cbd5e1;
--text-muted: #64748b;
--text-glow: #e0f2fe;
--force-radial: #00f0ff;
--force-axial: #ff5580;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: var(--bg-color);
font-family: 'JetBrains Mono', 'Noto Sans SC', monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
color: var(--text-glow);
}
#animation-container {
position: relative;
width: 90vw;
max-width: 1200px;
aspect-ratio: 16 / 9;
background: radial-gradient(circle at center, #0a1122 0%, #03060a 100%);
border: 1px solid rgba(56, 189, 248, 0.2);
border-radius: 8px;
box-shadow: 0 0 40px rgba(0, 0, 0, 0.8), inset 0 0 20px rgba(56, 189, 248, 0.05);
display: flex;
flex-direction: column;
}
svg {
width: 100%;
height: 100%;
display: block;
}
/* 文字排版严格遵循边缘化、小型化,确保不遮挡核心动画 */
.text-sm { font-size: 13px; fill: var(--text-muted); }
.text-md { font-size: 16px; font-weight: bold; fill: var(--text-glow); }
.text-data { font-size: 14px; fill: var(--outer-cone); font-weight: bold; }
.text-title { font-size: 20px; font-weight: bold; fill: #fff; letter-spacing: 1px; }
/* 控制面板 */
.controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 15px;
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(8px);
padding: 10px 24px;
border-radius: 30px;
border: 1px solid rgba(56, 189, 248, 0.3);
z-index: 10;
}
input[type=range] {
-webkit-appearance: none;
width: 200px;
background: transparent;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
background: #334155;
border-radius: 2px;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--outer-cone);
box-shadow: 0 0 10px var(--outer-cone);
margin-top: -6px;
cursor: pointer;
transition: transform 0.1s;
}
input[type=range]::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
#mode-status {
font-size: 12px;
color: var(--outer-cone);
min-width: 80px;
text-align: center;
}
.ifr-badge {
opacity: 0;
transition: opacity 0.3s;
}
.ifr-badge.active {
opacity: 1;
}
</style>
</head>
<body>
<div id="animation-container">
<svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 背景网格 -->
<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="1"/>
</pattern>
<!-- 材质截面剖面线 -->
<pattern id="hatch-hub" width="8" height="8" patternTransform="rotate(45)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="8" stroke="rgba(255,255,255,0.05)" stroke-width="2" />
</pattern>
<pattern id="hatch-shaft" width="10" height="10" patternTransform="rotate(-45)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" stroke="rgba(255,255,255,0.08)" stroke-width="1.5" />
</pattern>
<!-- 渐变质感 -->
<linearGradient id="inner-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#ff7e67"/>
<stop offset="100%" stop-color="#c44d3a"/>
</linearGradient>
<linearGradient id="outer-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#00f0ff"/>
<stop offset="100%" stop-color="#008a99"/>
</linearGradient>
<linearGradient id="bolt-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="50%" stop-color="#94a3b8"/>
<stop offset="100%" stop-color="#475569"/>
</linearGradient>
<!-- 发光滤镜 -->
<filter id="neon-glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 箭头标记 -->
<marker id="arrow-radial-up" viewBox="0 0 10 10" refX="5" refY="0" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 10 L 5 0 L 10 10 Z" fill="var(--force-radial)" />
</marker>
<marker id="arrow-axial-left" viewBox="0 0 10 10" refX="0" refY="5" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
<path d="M 10 0 L 0 5 L 10 10 Z" fill="var(--force-axial)" />
</marker>
</defs>
<!-- 背景 -->
<rect width="100%" height="100%" fill="url(#grid)" />
<!-- 静态标识与文字 (避开中心动画区) -->
<g transform="translate(40, 40)">
<text class="text-title" x="0" y="0">双锥面胀紧套原理动画</text>
<text class="text-sm" x="0" y="25">TRIZ IFR (理想最终解) 演示:消除间隙配合的矛盾</text>
<line x1="0" y1="40" x2="350" y2="40" stroke="rgba(255,255,255,0.2)" stroke-width="1" />
</g>
<!-- 图例 -->
<g transform="translate(40, 520)">
<rect x="0" y="0" width="12" height="12" fill="#111827" stroke="#334155" />
<text class="text-sm" x="20" y="11">轮毂/轴 (孔与轴)</text>
<rect x="140" y="0" width="12" height="12" fill="url(#outer-grad)" />
<text class="text-sm" x="160" y="11">外环 (内锥面)</text>
<rect x="280" y="0" width="12" height="12" fill="url(#inner-grad)" />
<text class="text-sm" x="300" y="11">内环 (外锥面)</text>
</g>
<!-- 遥测数据面板 (右上角) -->
<g transform="translate(780, 50)" class="telemetry">
<rect x="-15" y="-20" width="200" height="130" fill="rgba(15, 23, 42, 0.8)" rx="4" stroke="rgba(56,189,248,0.3)"/>
<text class="text-sm" x="0" y="0">实时状态监测 / STATUS</text>
<line x1="0" y1="10" x2="170" y2="10" stroke="rgba(56,189,248,0.3)" />
<text class="text-sm" x="0" y="35">预紧扭矩: <tspan id="data-torque" class="text-data">0.0</tspan> N·m</text>
<text class="text-sm" x="0" y="60">相对位移: <tspan id="data-disp" class="text-data">0.0</tspan> mm</text>
<text class="text-sm" x="0" y="85">配合间隙: <tspan id="data-gap" class="text-data">0.15</tspan> mm</text>
<!-- IFR 徽章 -->
<g id="ifr-badge" class="ifr-badge" transform="translate(0, 100)">
<rect x="0" y="-12" width="165" height="20" fill="rgba(0, 240, 255, 0.1)" rx="2" stroke="#00f0ff" stroke-width="1"/>
<text class="text-sm" x="82" y="2" fill="#00f0ff" text-anchor="middle" font-weight="bold">IFR 达成: 无隙过盈锁死</text>
</g>
</g>
<!-- 核心机械结构容器 (中心对齐) -->
<g id="mechanism" transform="translate(0, 0)">
<!-- 中心线 -->
<line x1="50" y1="300" x2="950" y2="300" stroke="#475569" stroke-width="1.5" stroke-dasharray="15, 5, 4, 5" />
<text class="text-sm" x="960" y="304" fill="#475569">CL</text>
<!-- 1. 外部轮毂 (Hub) 剖面 - 上半部分 -->
<path d="M 150 60 L 850 60 L 850 140 L 150 140 Z" fill="var(--hub-color)" stroke="var(--hub-stroke)" stroke-width="2" />
<path d="M 150 60 L 850 60 L 850 140 L 150 140 Z" fill="url(#hatch-hub)" />
<!-- 1. 外部轮毂 (Hub) 剖面 - 下半部分 -->
<path d="M 150 540 L 850 540 L 850 460 L 150 460 Z" fill="var(--hub-color)" stroke="var(--hub-stroke)" stroke-width="2" />
<path d="M 150 540 L 850 540 L 850 460 L 150 460 Z" fill="url(#hatch-hub)" />
<!-- 2. 内部轴 (Shaft) 剖面 - 上下完整 -->
<path d="M 100 240 L 900 240 L 900 360 L 100 360 Z" fill="var(--shaft-color)" stroke="var(--shaft-stroke)" stroke-width="2" />
<path d="M 100 240 L 900 240 L 900 360 L 100 360 Z" fill="url(#hatch-shaft)" />
<!-- 间隙高亮指示 (未锁紧时显示) -->
<g id="gap-indicators" stroke="#ffcc00" stroke-width="2" opacity="1">
<line x1="380" y1="144" x2="620" y2="144" stroke-dasharray="4,4" />
<line x1="380" y1="236" x2="620" y2="236" stroke-dasharray="4,4" />
<line x1="380" y1="364" x2="620" y2="364" stroke-dasharray="4,4" />
<line x1="380" y1="456" x2="620" y2="456" stroke-dasharray="4,4" />
</g>
<!-- 3. 外环 (Inner Cone) -->
<g id="outer-ring-top">
<!-- 外环法兰在左侧, 上方平面, 下方斜面 -->
<path d="M 330 148 L 650 148 L 650 216 L 380 162 L 380 230 L 330 230 Z" fill="url(#outer-grad)" stroke="#00b8c4" stroke-width="1" />
</g>
<g id="outer-ring-bottom">
<path d="M 330 452 L 650 452 L 650 384 L 380 438 L 380 370 L 330 370 Z" fill="url(#outer-grad)" stroke="#00b8c4" stroke-width="1" />
</g>
<!-- 4. 内环 (Outer Cone) -->
<g id="inner-ring-top">
<!-- 内环斜面贴合, 底部平面 -->
<path d="M 380 232 L 650 232 L 650 216 L 380 162 Z" fill="url(#inner-grad)" stroke="#c44d3a" stroke-width="1" />
<line id="wedge-glow-top" x1="380" y1="162" x2="650" y2="216" stroke="#00f0ff" stroke-width="3" filter="url(#neon-glow)" opacity="0"/>
</g>
<g id="inner-ring-bottom">
<path d="M 380 368 L 650 368 L 650 384 L 380 438 Z" fill="url(#inner-grad)" stroke="#c44d3a" stroke-width="1" />
<line id="wedge-glow-bottom" x1="380" y1="438" x2="650" y2="384" stroke="#00f0ff" stroke-width="3" filter="url(#neon-glow)" opacity="0"/>
</g>
<!-- 5. 高强度螺栓 (Bolt) -->
<g id="bolt-top">
<!-- 螺栓头 -->
<rect x="290" y="180" width="40" height="20" rx="2" fill="url(#bolt-grad)" stroke="#334155"/>
<!-- 螺柱穿过外环法兰进入内环 -->
<rect x="330" y="186" width="180" height="8" fill="url(#bolt-grad)" stroke="#334155"/>
<!-- 螺纹标识 -->
<path d="M 420 186 L 420 194 M 430 186 L 430 194 M 440 186 L 440 194 M 450 186 L 450 194 M 460 186 L 460 194 M 470 186 L 470 194 M 480 186 L 480 194 M 490 186 L 490 194 M 500 186 L 500 194" stroke="#475569" stroke-width="1"/>
</g>
<g id="bolt-bottom">
<!-- 螺栓头 -->
<rect x="290" y="400" width="40" height="20" rx="2" fill="url(#bolt-grad)" stroke="#334155"/>
<!-- 螺柱 -->
<rect x="330" y="406" width="180" height="8" fill="url(#bolt-grad)" stroke="#334155"/>
<!-- 螺纹标识 -->
<path d="M 420 406 L 420 414 M 430 406 L 430 414 M 440 406 L 440 414 M 450 406 L 450 414 M 460 406 L 460 414 M 470 406 L 470 414 M 480 406 L 480 414 M 490 406 L 490 414 M 500 406 L 500 414" stroke="#475569" stroke-width="1"/>
</g>
<!-- 6. 力学指示箭头 (受力时显现) -->
<g id="force-arrows" opacity="0">
<!-- 轴向预紧力 (螺栓拉力) -->
<line x1="380" y1="170" x2="310" y2="170" stroke="var(--force-axial)" stroke-width="2" marker-end="url(#arrow-axial-left)" filter="url(#neon-glow)"/>
<line x1="380" y1="430" x2="310" y2="430" stroke="var(--force-axial)" stroke-width="2" marker-end="url(#arrow-axial-left)" filter="url(#neon-glow)"/>
<text class="text-sm" x="290" y="160" fill="var(--force-axial)">F_axial (拉扯内环)</text>
<!-- 径向正压力 (胀紧孔壁与轴壁) -->
<!-- 上轮毂压紧 -->
<g stroke="var(--force-radial)" stroke-width="2" marker-start="url(#arrow-radial-up)" filter="url(#neon-glow)">
<line x1="420" y1="130" x2="420" y2="148" />
<line x1="500" y1="130" x2="500" y2="148" />
<line x1="580" y1="130" x2="580" y2="148" />
</g>
<!-- 上轴壁压紧 -->
<g stroke="var(--force-radial)" stroke-width="2" marker-start="url(#arrow-radial-up)" filter="url(#neon-glow)">
<line x1="420" y1="250" x2="420" y2="232" />
<line x1="500" y1="250" x2="500" y2="232" />
<line x1="580" y1="250" x2="580" y2="232" />
</g>
<!-- 下轴壁压紧 -->
<g stroke="var(--force-radial)" stroke-width="2" marker-start="url(#arrow-radial-up)" filter="url(#neon-glow)">
<line x1="420" y1="350" x2="420" y2="368" />
<line x1="500" y1="350" x2="500" y2="368" />
<line x1="580" y1="350" x2="580" y2="368" />
</g>
<!-- 下轮毂压紧 -->
<g stroke="var(--force-radial)" stroke-width="2" marker-start="url(#arrow-radial-up)" filter="url(#neon-glow)">
<line x1="420" y1="470" x2="420" y2="452" />
<line x1="500" y1="470" x2="500" y2="452" />
<line x1="580" y1="470" x2="580" y2="452" />
</g>
<text class="text-sm" x="600" y="125" fill="var(--force-radial)">P_radial (径向贴合锁死)</text>
</g>
</g>
</svg>
<!-- 底部交互控制 -->
<div class="controls">
<input type="range" id="manual-slider" min="0" max="1" step="0.001" value="0">
<span id="mode-status">自动播放中...</span>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
// 核心动画参数
const CONFIG = {
maxDisplacementX: -45, // 内环向左最大位移
maxDisplacementY: 8, // 径向最大膨胀位移(单侧)
maxTorque: 30, // N·m
initialGap: 0.15 // mm
};
// DOM 元素引用
const els = {
innerTop: document.getElementById('inner-ring-top'),
innerBottom: document.getElementById('inner-ring-bottom'),
outerTop: document.getElementById('outer-ring-top'),
outerBottom: document.getElementById('outer-ring-bottom'),
boltTop: document.getElementById('bolt-top'),
boltBottom: document.getElementById('bolt-bottom'),
gapIndicators: document.getElementById('gap-indicators'),
forceArrows: document.getElementById('force-arrows'),
wedgeGlowTop: document.getElementById('wedge-glow-top'),
wedgeGlowBottom: document.getElementById('wedge-glow-bottom'),
slider: document.getElementById('manual-slider'),
statusText: document.getElementById('mode-status'),
dataTorque: document.getElementById('data-torque'),
dataDisp: document.getElementById('data-disp'),
dataGap: document.getElementById('data-gap'),
ifrBadge: document.getElementById('ifr-badge')
};
// 动画状态
let state = {
progress: 0,
direction: 1,
isAutoPlaying: true,
speed: 0.004
};
// 缓动函数 (平滑加减速)
const easeInOutCubic = t => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
// 核心渲染逻辑
function updateVisuals(p) {
const eased = easeInOutCubic(p);
// 物理位移计算 (楔形效应转换)
// 内环向左(X)移动,由于锥面作用,内环被迫向下(Y)移动,外环被迫向上(Y)移动,实现双向抱死
const dx = CONFIG.maxDisplacementX * eased;
const dy = CONFIG.maxDisplacementY * eased;
// 应用 Transform
els.innerTop.setAttribute('transform', `translate(${dx}, ${dy/2})`);
els.outerTop.setAttribute('transform', `translate(0, ${-dy/2})`);
els.innerBottom.setAttribute('transform', `translate(${dx}, ${-dy/2})`);
els.outerBottom.setAttribute('transform', `translate(0, ${dy/2})`);
// 螺栓虽内环旋进视觉上相对外环向左移动
els.boltTop.setAttribute('transform', `translate(${dx*0.2}, 0)`);
els.boltBottom.setAttribute('transform', `translate(${dx*0.2}, 0)`);
// 视觉特效与数据更新
const isTight = p > 0.8;
const tightRatio = isTight ? (p - 0.8) * 5 : 0; // 0 to 1
els.gapIndicators.setAttribute('opacity', 1 - eased);
els.forceArrows.setAttribute('opacity', tightRatio);
els.wedgeGlowTop.setAttribute('opacity', tightRatio * 0.8);
els.wedgeGlowBottom.setAttribute('opacity', tightRatio * 0.8);
// 更新遥测数据
els.dataTorque.textContent = (CONFIG.maxTorque * tightRatio).toFixed(1);
els.dataDisp.textContent = Math.abs(dx * 0.05).toFixed(2);
const currentGap = Math.max(0, CONFIG.initialGap - (dy * 0.02));
els.dataGap.textContent = currentGap.toFixed(2);
// IFR 状态徽章切换
if (currentGap <= 0.01 && !els.ifrBadge.classList.contains('active')) {
els.ifrBadge.classList.add('active');
els.dataGap.style.fill = "#00f0ff";
} else if (currentGap > 0.01 && els.ifrBadge.classList.contains('active')) {
els.ifrBadge.classList.remove('active');
els.dataGap.style.fill = "var(--outer-cone)";
}
// 同步滑块位置
if(state.isAutoPlaying) {
els.slider.value = p;
}
}
// 自动播放循环
function animate() {
if (state.isAutoPlaying) {
state.progress += state.speed * state.direction;
// 在两端停留片刻
if (state.progress > 1.3) {
state.progress = 1.3;
state.direction = -1;
} else if (state.progress < -0.2) {
state.progress = -0.2;
state.direction = 1;
}
// 限制传入更新函数的范围在 0-1
updateVisuals(Math.max(0, Math.min(1, state.progress)));
}
requestAnimationFrame(animate);
}
// 交互事件绑定
els.slider.addEventListener('input', (e) => {
state.isAutoPlaying = false;
els.statusText.textContent = "手动控制中";
els.statusText.style.color = "#ff7e67";
updateVisuals(parseFloat(e.target.value));
});
// 点击背景恢复自动播放
document.getElementById('animation-container').addEventListener('dblclick', () => {
if(!state.isAutoPlaying) {
state.isAutoPlaying = true;
state.progress = parseFloat(els.slider.value);
els.statusText.textContent = "自动播放中...";
els.statusText.style.color = "var(--outer-cone)";
}
});
// 启动
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
