独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TRIZ 最终理想解:轴端开花涨紧结构原理</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
:root {
--bg-color: #0b0f19;
--grid-color: rgba(45, 61, 94, 0.3);
--text-main: #a3b8cc;
--text-accent: #00f0ff;
--accent-orange: #ff5500;
--metal-dark: #1e2638;
--metal-mid: #3a475e;
--metal-light: #7b8ea8;
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-main);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.canvas-container {
position: relative;
width: 100%;
max-width: 1200px;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-height: 800px;
filter: drop-shadow(0 0 30px rgba(0, 240, 255, 0.05));
}
/* Peripheral UI Text Styling */
.info-panel {
position: absolute;
background: rgba(11, 15, 25, 0.85);
backdrop-filter: blur(8px);
border: 1px solid rgba(0, 240, 255, 0.15);
border-radius: 8px;
padding: 1rem;
pointer-events: none;
z-index: 10;
}
.title-panel {
top: 2rem;
left: 2rem;
border-left: 3px solid var(--text-accent);
}
.params-panel {
top: 2rem;
right: 2rem;
text-align: right;
border-right: 3px solid var(--accent-orange);
}
.desc-panel {
bottom: 2rem;
left: 2rem;
max-width: 380px;
border-bottom: 3px solid var(--metal-light);
}
.glow-text {
color: var(--text-accent);
text-shadow: 0 0 10px rgba(0, 240, 255, 0.4);
}
.glow-orange {
color: var(--accent-orange);
text-shadow: 0 0 10px rgba(255, 85, 0, 0.4);
}
/* Structural SVG CSS */
.svg-metal-path {
stroke: var(--metal-light);
stroke-width: 1.5;
stroke-linejoin: round;
}
.svg-hatch {
fill: url(#hatchPattern);
}
.lock-indicator {
opacity: 0;
transition: opacity 0.1s;
}
.force-arrow {
fill: var(--accent-orange);
filter: drop-shadow(0 0 5px var(--accent-orange));
}
</style>
</head>
<body>
<div class="canvas-container">
<!-- Floating UI Overlays -->
<div class="info-panel title-panel">
<h1 class="text-lg font-bold text-white tracking-wider mb-1">最终理想解 (IFR) <span class="text-xs text-gray-500 ml-2">v1.0</span></h1>
<p class="text-sm glow-text font-mono">轴端开花涨紧结构原理</p>
<div class="mt-2 text-xs text-gray-400">
利用系统内部资源(轴自身),无需第三方套筒,<br>突破极小空间限制,实现配合间隙自补偿。
</div>
</div>
<div class="info-panel params-panel">
<h2 class="text-sm font-bold text-white mb-2">关键工程参数</h2>
<ul class="text-xs space-y-1 text-gray-400 font-mono">
<li>十字槽长度: <span class="glow-orange">1.5 × D</span> (轴径)</li>
<li>中心锥销干涉量: <span class="glow-orange">0.15 mm</span></li>
<li>初始装配状态: <span class="text-green-400">微间隙滑动配合</span></li>
<li>最终工作状态: <span class="text-red-400">过盈极压锁死</span></li>
</ul>
</div>
<div class="info-panel desc-panel">
<h3 class="text-sm font-bold text-white mb-2 flex items-center">
<svg class="w-4 h-4 mr-2 glow-text" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path></svg>
动态机理分析
</h3>
<ol class="text-xs space-y-1.5 text-gray-300 list-decimal pl-4">
<li>带深盲孔与十字开口槽的柔性轴端轻松滑入孔内。</li>
<li>外部施加轴向载荷打入带有细微锥度的金属锥销。</li>
<li>锥面产生楔形增力效应,迫使轴端外壁呈“开花状”径向膨胀。</li>
<li><span class="glow-orange">达成 IFR:</span>孔轴界面由间隙瞬间转为高摩擦力过盈配合,彻底锁死。</li>
</ol>
</div>
<!-- Main SVG Animation -->
<svg viewBox="0 0 1000 700" preserveAspectRatio="xMidYMid meet" id="main-svg">
<defs>
<!-- Grid Pattern -->
<pattern id="blueprintGrid" 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"/>
<path d="M 200 0 L 0 0 0 200" fill="none" stroke="var(--grid-color)" stroke-width="1"/>
</pattern>
<!-- Metal Hatching for Cutaway Sections -->
<pattern id="hatchPattern" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" stroke="#2a354d" stroke-width="2" />
</pattern>
<!-- Gradients -->
<linearGradient id="holeMetal" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#151b26"/>
<stop offset="100%" stop-color="#222b3d"/>
</linearGradient>
<linearGradient id="holeMetalRight" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#222b3d"/>
<stop offset="100%" stop-color="#151b26"/>
</linearGradient>
<linearGradient id="shaftMetal" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#4a5a75"/>
<stop offset="50%" stop-color="#8a9ba8"/>
<stop offset="100%" stop-color="#3a475e"/>
</linearGradient>
<linearGradient id="pinMetal" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#cc4400"/>
<stop offset="50%" stop-color="#ff7733"/>
<stop offset="100%" stop-color="#993300"/>
</linearGradient>
<!-- Glow Filters -->
<filter id="glowGlow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="1000" height="700" fill="url(#blueprintGrid)" />
<!-- Center Axis Line -->
<line x1="500" y1="50" x2="500" y2="650" stroke="rgba(0, 240, 255, 0.3)" stroke-width="1" stroke-dasharray="15, 10, 3, 10" />
<text x="510" y="70" fill="rgba(0, 240, 255, 0.5)" font-size="10" font-family="monospace">CENTER AXIS (CL)</text>
<g id="scene-container" transform="translate(0, 50)">
<!-- HOLE COMPONENT (Outer shell, cross-section) -->
<!-- Left Hole Body -->
<path d="M 200,100 L 416,100 L 416,500 L 200,500 Z" fill="url(#holeMetal)" class="svg-metal-path" />
<path d="M 200,100 L 416,100 L 416,500 L 200,500 Z" fill="url(#hatchPattern)" opacity="0.6"/>
<!-- Right Hole Body -->
<path d="M 800,100 L 584,100 L 584,500 L 800,500 Z" fill="url(#holeMetalRight)" class="svg-metal-path" />
<path d="M 800,100 L 584,100 L 584,500 L 800,500 Z" fill="url(#hatchPattern)" opacity="0.6"/>
<text x="220" y="130" fill="rgba(255,255,255,0.3)" font-size="12" font-family="monospace">OUTER HOLE</text>
<text x="700" y="130" fill="rgba(255,255,255,0.3)" font-size="12" font-family="monospace">OUTER HOLE</text>
<!-- INITIAL GAP VISUALIZATION (Background lines) -->
<line x1="418" y1="100" x2="418" y2="400" stroke="#00f0ff" stroke-width="1" opacity="0.3" stroke-dasharray="2,2"/>
<line x1="582" y1="100" x2="582" y2="400" stroke="#00f0ff" stroke-width="1" opacity="0.3" stroke-dasharray="2,2"/>
<!-- SHAFT COMPONENT -->
<!-- Shaft Base (Solid part below the slot) -->
<path d="M 420,400 L 580,400 L 580,600 L 420,600 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
<text x="475" y="550" fill="rgba(255,255,255,0.5)" font-size="12" font-family="monospace" letter-spacing="2">MAIN SHAFT</text>
<!-- Left Expanding Arm (Pivot at 460, 400) -->
<g id="left-arm">
<path d="M 420,100 L 485,100 L 490,400 L 420,400 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
<!-- Slot depth indicator -->
<line x1="488" y1="100" x2="490" y2="400" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
</g>
<!-- Right Expanding Arm (Pivot at 540, 400) -->
<g id="right-arm">
<path d="M 580,100 L 515,100 L 510,400 L 580,400 Z" fill="url(#shaftMetal)" class="svg-metal-path" />
<line x1="512" y1="100" x2="510" y2="400" stroke="rgba(255,255,255,0.2)" stroke-width="1"/>
</g>
<!-- Cross-slot centerline (Visual depth) -->
<line x1="500" y1="100" x2="500" y2="400" stroke="rgba(0,0,0,0.5)" stroke-width="2" stroke-dasharray="4,2"/>
<!-- TAPERED PIN -->
<g id="taper-pin-group">
<g id="taper-pin">
<!-- Pin Body -->
<polygon points="480,-50 520,-50 514,250 486,250" fill="url(#pinMetal)" stroke="#ff9966" stroke-width="1.5" />
<!-- Pin Top Cap -->
<path d="M 476,-50 L 524,-50 L 524,-60 L 476,-60 Z" fill="#ff7733" />
<!-- Force Arrows applied to Pin -->
<g id="force-arrows" opacity="0">
<path d="M 500,-100 L 500,-70" stroke="var(--accent-orange)" stroke-width="3" stroke-linecap="round" />
<polygon points="500,-65 495,-75 505,-75" fill="var(--accent-orange)" />
<text x="515" y="-80" fill="var(--accent-orange)" font-size="12" font-family="monospace" font-weight="bold">F (AXIAL LOAD)</text>
</g>
</g>
</g>
<!-- LOCKING HIGHLIGHTS & EFFECTS (Appear on interference) -->
<g class="lock-indicator" id="lock-effects">
<!-- Left Wall Glow -->
<line x1="416" y1="100" x2="416" y2="350" stroke="#ff3300" stroke-width="6" filter="url(#glowGlow)" opacity="0.8" />
<line x1="416" y1="100" x2="416" y2="350" stroke="#ffffff" stroke-width="2" />
<!-- Right Wall Glow -->
<line x1="584" y1="100" x2="584" y2="350" stroke="#ff3300" stroke-width="6" filter="url(#glowGlow)" opacity="0.8" />
<line x1="584" y1="100" x2="584" y2="350" stroke="#ffffff" stroke-width="2" />
<!-- Radial Force Arrows (Internal) -->
<g opacity="0.8" stroke="var(--text-accent)" stroke-width="1.5" fill="none">
<!-- Left pushes -->
<path d="M 480,150 L 430,150" marker-end="url(#arrowCyan)"/>
<path d="M 483,250 L 430,250" marker-end="url(#arrowCyan)"/>
<path d="M 486,350 L 430,350" marker-end="url(#arrowCyan)"/>
<!-- Right pushes -->
<path d="M 520,150 L 570,150" marker-end="url(#arrowCyan)"/>
<path d="M 517,250 L 570,250" marker-end="url(#arrowCyan)"/>
<path d="M 514,350 L 570,350" marker-end="url(#arrowCyan)"/>
</g>
<text x="320" y="250" fill="#ff5500" font-size="12" font-family="monospace" font-weight="bold" filter="url(#glowGlow)">↑ INTERFERENCE FIT</text>
<text x="680" y="250" fill="#ff5500" font-size="12" font-family="monospace" font-weight="bold" filter="url(#glowGlow)">INTERFERENCE FIT ↑</text>
</g>
</g>
<!-- Markers definition (must be outside scaled groups or carefully managed) -->
<defs>
<marker id="arrowCyan" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 1 L 10 5 L 0 9 z" fill="var(--text-accent)" />
</marker>
</defs>
<!-- Dimension Lines (Static UI layer in SVG) -->
<g stroke="rgba(163, 184, 204, 0.4)" stroke-width="1" fill="none" font-family="monospace" font-size="10" text-anchor="middle">
<!-- Slot Length -->
<line x1="390" y1="150" x2="390" y2="450" />
<line x1="385" y1="150" x2="395" y2="150" />
<line x1="385" y1="450" x2="395" y2="450" />
<text x="375" y="305" fill="rgba(163, 184, 204, 0.8)" transform="rotate(-90, 375, 305)">SLOT LENGTH ≈ 1.5D</text>
<!-- Initial Clearance (Exaggerated for diagram) -->
<line x1="416" y1="80" x2="416" y2="90" />
<line x1="420" y1="80" x2="420" y2="90" />
<line x1="416" y1="85" x2="400" y2="85" />
<line x1="420" y1="85" x2="436" y2="85" />
<text x="418" y="75" fill="rgba(0, 240, 255, 0.8)">CLEARANCE</text>
</g>
</svg>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const pin = document.getElementById('taper-pin');
const leftArm = document.getElementById('left-arm');
const rightArm = document.getElementById('right-arm');
const forceArrows = document.getElementById('force-arrows');
const lockEffects = document.getElementById('lock-effects');
// Animation Parameters
const cycleDuration = 4000; // Total ms per cycle (down, hold, up, hold)
// Physical boundaries in SVG space
const pinStartY = -100;
const pinEndY = 150; // Pin descends 250 units
const maxAngle = 1.2; // Degrees arms rotate outwards to close the gap
// Arm Pivots
const leftPivotX = 460;
const rightPivotX = 540;
const pivotY = 400;
let startTimestamp = null;
function easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
function animate(timestamp) {
if (!startTimestamp) startTimestamp = timestamp;
// Progress from 0 to 1 over the cycle duration
const elapsed = timestamp - startTimestamp;
const rawProgress = (elapsed % cycleDuration) / cycleDuration;
// Create a timeline within the cycle:
// 0.0 - 0.1: Hold top
// 0.1 - 0.4: Drive pin down (expand)
// 0.4 - 0.6: Hold bottom (locked state, IFR)
// 0.6 - 0.9: Pull pin up (retract)
// 0.9 - 1.0: Hold top
let motionPhase = 0; // 0 (top) to 1 (bottom)
let isLocked = false;
if (rawProgress < 0.1) {
motionPhase = 0;
} else if (rawProgress < 0.4) {
const localP = (rawProgress - 0.1) / 0.3;
motionPhase = easeInOutCubic(localP);
} else if (rawProgress < 0.6) {
motionPhase = 1;
isLocked = true;
} else if (rawProgress < 0.9) {
const localP = (rawProgress - 0.6) / 0.3;
motionPhase = 1 - easeInOutCubic(localP);
} else {
motionPhase = 0;
}
// Calculate positions based on phase
const currentPinY = pinStartY + (pinEndY - pinStartY) * motionPhase;
const currentAngle = maxAngle * motionPhase;
// Apply Transforms
pin.setAttribute('transform', `translate(0, ${currentPinY})`);
// Left arm rotates counter-clockwise (-), Right arm clockwise (+)
leftArm.setAttribute('transform', `rotate(${-currentAngle}, ${leftPivotX}, ${pivotY})`);
rightArm.setAttribute('transform', `rotate(${currentAngle}, ${rightPivotX}, ${pivotY})`);
// UI Opacity Updates
// Force arrows appear while driving down (0.1 to 0.4)
if (rawProgress >= 0.1 && rawProgress <= 0.4) {
const p = (rawProgress - 0.1) / 0.3;
forceArrows.style.opacity = Math.sin(p * Math.PI); // Fade in and out
} else {
forceArrows.style.opacity = 0;
}
// Lock effects pulse when locked
if (isLocked) {
// Quick fade in, then hold
const lockTime = (rawProgress - 0.4) / 0.2; // 0 to 1 during lock phase
// Add a slight pulse effect
const pulse = 0.8 + 0.2 * Math.sin(lockTime * Math.PI * 4);
lockEffects.style.opacity = pulse;
} else if (rawProgress > 0.35 && rawProgress < 0.4) {
// Quick fade in right before lock
lockEffects.style.opacity = (rawProgress - 0.35) / 0.05;
} else if (rawProgress > 0.6 && rawProgress < 0.65) {
// Quick fade out right after lock
lockEffects.style.opacity = 1 - ((rawProgress - 0.6) / 0.05);
} else {
lockEffects.style.opacity = 0;
}
requestAnimationFrame(animate);
}
// Start animation loop
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
