独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>偏心阶梯孔垂直强制导向原理动画</title>
<style>
:root {
/* 极简工业暗黑美学 / Blueprint / Precision */
--bg-base: #050505;
--bg-grid: #171717;
--panel-border: #27272a;
--text-main: #a1a1aa;
--text-dim: #52525b;
--text-bright: #f4f4f5;
/* 核心标识色 */
--color-ifr-cyan: #0ea5e9; /* 理想解:垂直承重墙 */
--color-force-amber: #f59e0b; /* 作用力:磨削力 */
--color-spring: #fbbf24; /* 工件:弹簧 */
--color-disk: #27272a; /* 基体:磨盘 */
--font-mono: 'JetBrains Mono', 'Consolas', 'Courier New', monospace;
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-base);
color: var(--text-main);
font-family: var(--font-sans);
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
/* 工业网格背景 */
background-image:
linear-gradient(var(--bg-grid) 1px, transparent 1px),
linear-gradient(90deg, var(--bg-grid) 1px, transparent 1px);
background-size: 40px 40px;
background-position: center center;
}
/* 绝对避免遮挡中央动画的边缘排版 */
header {
position: absolute;
top: 24px;
left: 32px;
z-index: 10;
pointer-events: none;
}
.sys-title {
font-family: var(--font-mono);
font-size: 14px;
color: var(--text-bright);
letter-spacing: 1px;
font-weight: 600;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.sys-title::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
background-color: var(--color-ifr-cyan);
border-radius: 50%;
box-shadow: 0 0 8px var(--color-ifr-cyan);
}
.sys-desc {
font-size: 12px;
max-width: 320px;
line-height: 1.6;
color: var(--text-dim);
}
.telemetry {
position: absolute;
top: 24px;
right: 32px;
text-align: right;
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-dim);
z-index: 10;
}
.telemetry .status-indicator {
color: var(--color-ifr-cyan);
animation: pulse 2s infinite;
}
.footer-info {
position: absolute;
bottom: 24px;
left: 32px;
right: 32px;
display: flex;
justify-content: space-between;
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-dim);
border-top: 1px solid var(--panel-border);
padding-top: 12px;
z-index: 10;
}
/* 中央视口,最大化核心动画空间 */
.stage {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
height: 100%;
}
svg {
width: 100%;
max-width: 1200px;
height: auto;
max-height: 80vh;
filter: drop-shadow(0 0 30px rgba(0,0,0,0.5));
}
@keyframes pulse {
0%, 100% { opacity: 0.5; }
50% { opacity: 1; }
}
/* 隐藏滚动条 */
::-webkit-scrollbar { display: none; }
</style>
</head>
<body>
<header>
<div class="sys-title">TRIZ_IFR: 偏心阶梯孔(斜度锥孔)强制导向模型</div>
<div class="sys-desc">
消除“点头/翘尾”效应。<br>
直接利用磨削力作为驱动源,将弹簧推向高精度半圆柱面(受力侧2.02mm)。非受力侧保留0.15~0.2mm避空,实现零斜率垂直贴合。
</div>
</header>
<div class="telemetry">
<div class="status-indicator">● RUNNING</div>
<div>T_CYCLE: 6000ms</div>
<div id="phase-readout">PHASE: STANDBY</div>
</div>
<main class="stage">
<!-- 主SVG视口,基于 viewBox 确保自适应与极佳空间布局 -->
<svg id="canvas" viewBox="0 0 1200 600" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 滤镜定义:高精度墙面发光 (理想解) -->
<filter id="glowCyan" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur1" />
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur2" />
<feMerge>
<feMergeNode in="blur2" />
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 滤镜定义:作用力发光 -->
<filter id="glowAmber" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur1" />
<feMerge>
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 材料剖面填充纹理 (磨盘基体) -->
<pattern id="hatch" width="8" height="8" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="8" stroke="#18181b" stroke-width="1.5" />
</pattern>
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="var(--color-force-amber)" />
</marker>
</defs>
<!-- ============================================== -->
<!-- 左侧面板:X-Y 俯视图 (偏心葫芦形孔) -->
<!-- ============================================== -->
<g transform="translate(300, 300)" id="top-view">
<!-- 坐标系辅助线 -->
<line x1="-150" y1="0" x2="150" y2="0" stroke="#27272a" stroke-width="1" stroke-dasharray="4 4" />
<line x1="0" y1="-150" x2="0" y2="150" stroke="#27272a" stroke-width="1" stroke-dasharray="4 4" />
<!-- 视图标签 -->
<text x="-150" y="-130" fill="var(--text-dim)" font-family="var(--font-mono)" font-size="12">TOP VIEW (X-Y Plane)</text>
<text x="-150" y="-110" fill="var(--text-dim)" font-family="var(--font-mono)" font-size="10">Scale: ~1:40 (Exaggerated for clarity)</text>
<!-- 磨盘基体外缘 -->
<circle cx="0" cy="0" r="140" fill="transparent" stroke="#27272a" stroke-width="2" />
<!-- 偏心葫芦形孔底色 -->
<path d="M -30,44 A 44,44 0 1,0 30,44 L 25,-40.4 A 40.4,40.4 0 1,1 -25,-40.4 Z" fill="#09090b" stroke="#3f3f46" stroke-width="2" />
<!-- 尺寸标注 -->
<text x="60" y="70" fill="#52525b" font-family="var(--font-mono)" font-size="11">Ø2.20mm (下料侧)</text>
<text x="60" y="-50" fill="var(--color-ifr-cyan)" font-family="var(--font-mono)" font-size="11">Ø2.02mm (高精度承重侧)</text>
<!-- 核心理想解:高精度半圆面高亮 (初始隐藏) -->
<path id="top-wall-glow" d="M -40.4,-40.4 A 40.4,40.4 0 0,1 40.4,-40.4" fill="transparent" stroke="var(--color-ifr-cyan)" stroke-width="3" filter="url(#glowCyan)" opacity="0" />
<!-- 工件(弹簧) 俯视 -->
<g id="top-spring">
<circle cx="0" cy="0" r="40" fill="#27272a" stroke="var(--color-spring)" stroke-width="2" />
<!-- 弹簧内部结构示意 -->
<circle cx="0" cy="0" r="30" fill="transparent" stroke="var(--color-spring)" stroke-width="0.5" stroke-dasharray="2 2" />
<circle cx="0" cy="0" r="20" fill="transparent" stroke="var(--color-spring)" stroke-width="0.5" stroke-dasharray="2 2" />
</g>
<!-- 磨削力指示箭头 (俯视) -->
<g id="top-force" opacity="0">
<line x1="0" y1="90" x2="0" y2="45" stroke="var(--color-force-amber)" stroke-width="3" marker-end="url(#arrow)" filter="url(#glowAmber)" />
<text x="10" y="85" fill="var(--color-force-amber)" font-family="var(--font-mono)" font-size="11" filter="url(#glowAmber)">F_grind</text>
</g>
</g>
<!-- 分隔线 -->
<line x1="600" y1="100" x2="600" y2="500" stroke="#27272a" stroke-width="1" stroke-dasharray="4 4" />
<!-- ============================================== -->
<!-- 右侧面板:Z轴剖视图 (垂直度强制导向) -->
<!-- ============================================== -->
<g transform="translate(900, 300)" id="side-view">
<!-- 坐标系辅助线 -->
<line x1="-200" y1="160" x2="200" y2="160" stroke="#27272a" stroke-width="1" stroke-dasharray="4 4" /> <!-- 底部基准 -->
<text x="-250" y="-200" fill="var(--text-dim)" font-family="var(--font-mono)" font-size="12">SECTION VIEW (Y-Z Plane)</text>
<!-- 磨盘基体 (厚度8mm映射为320px) -->
<!-- 左侧基体 (避空侧, 较宽) -->
<rect x="-150" y="-160" width="106" height="320" fill="url(#hatch)" stroke="#3f3f46" stroke-width="2" />
<!-- 右侧基体 (高精度承重墙) -->
<rect x="40.4" y="-160" width="109.6" height="320" fill="url(#hatch)" stroke="#3f3f46" stroke-width="2" />
<!-- 剖视图孔的轮廓线 -->
<line x1="-44" y1="-160" x2="-44" y2="160" stroke="#52525b" stroke-width="1.5" /> <!-- 左壁 (大孔边界) -->
<line x1="40.4" y1="-160" x2="40.4" y2="160" stroke="#52525b" stroke-width="1.5" /> <!-- 右壁 (绝对垂直面) -->
<!-- 核心理想解:垂直承重墙高亮 -->
<line id="side-wall-glow" x1="40.4" y1="-160" x2="40.4" y2="160" stroke="var(--color-ifr-cyan)" stroke-width="4" filter="url(#glowCyan)" opacity="0" />
<text id="side-wall-text" x="60" y="0" fill="var(--color-ifr-cyan)" font-family="var(--font-sans)" font-size="12" font-weight="bold" filter="url(#glowCyan)" opacity="0">绝对垂直承重墙 (100%贴合)</text>
<text id="side-gap-text" x="-140" y="0" fill="var(--text-dim)" font-family="var(--font-mono)" font-size="11" opacity="0">避空余量: 0.15mm</text>
<!-- 工件(弹簧) 侧视 -->
<g id="side-spring">
<!-- 弹簧外轮廓包络线 -->
<rect x="-40" y="-160" width="80" height="320" fill="#18181b" stroke="var(--color-spring)" stroke-width="1.5" opacity="0.8" />
<!-- 内部波浪线模拟弹簧绕线 -->
<path d="M -40,-150 L 40,-130 L -40,-110 L 40,-90 L -40,-70 L 40,-50 L -40,-30 L 40,-10 L -40,10 L 40,30 L -40,50 L 40,70 L -40,90 L 40,110 L -40,130 L 40,150" fill="transparent" stroke="var(--color-spring)" stroke-width="2" opacity="0.6" />
</g>
<!-- 砂轮与磨削力 (侧视) -->
<g id="grinding-wheel" transform="translate(0, -220)">
<rect x="-100" y="-40" width="200" height="40" fill="#3f3f46" rx="5" />
<rect x="-100" y="0" width="200" height="10" fill="var(--color-force-amber)" />
<text x="110" y="-15" fill="var(--text-dim)" font-family="var(--font-mono)" font-size="11">砂轮 (Grinding Wheel)</text>
</g>
<!-- 磨削力箭头 (侧视) -->
<g id="side-force" opacity="0">
<line x1="-80" y1="-120" x2="-45" y2="-120" stroke="var(--color-force-amber)" stroke-width="3" marker-end="url(#arrow)" filter="url(#glowAmber)" />
<text x="-120" y="-116" fill="var(--color-force-amber)" font-family="var(--font-mono)" font-size="11" filter="url(#glowAmber)">推力</text>
</g>
<!-- 磨削火花层 (通过JS动态生成) -->
<g id="sparks"></g>
</g>
</svg>
</main>
<div class="footer-info">
<div>[TRIZ_PRINCIPLE] 资源利用 / 局部质量 (最终理想解)</div>
<div>ENGINE: VanillaJS / CSS / SVG_SMIL</div>
</div>
<script>
/**
* 绝对安全:无外部依赖,纯原生实现的核心动画逻辑。
* 基于 requestAnimationFrame 的无缝状态机,保证"重开即播"及"自动循环"
*/
const TOTAL_DURATION = 6000; // 6秒一个循环
// DOM 元素引用
const topSpring = document.getElementById('top-spring');
const topForce = document.getElementById('top-force');
const topWallGlow = document.getElementById('top-wall-glow');
const sideSpring = document.getElementById('side-spring');
const sideForce = document.getElementById('side-force');
const sideWallGlow = document.getElementById('side-wall-glow');
const sideWallText = document.getElementById('side-wall-text');
const sideGapText = document.getElementById('side-gap-text');
const grindingWheel = document.getElementById('grinding-wheel');
const sparksContainer = document.getElementById('sparks');
const phaseReadout = document.getElementById('phase-readout');
// 插值函数
const lerp = (start, end, t) => start + (end - start) * t;
const easeInOut = t => t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
// 火花池管理
const sparkPool = [];
for(let i=0; i<15; i++) {
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute("stroke", "var(--color-force-amber)");
line.setAttribute("stroke-width", Math.random() * 1.5 + 0.5);
line.setAttribute("opacity", "0");
sparksContainer.appendChild(line);
sparkPool.push({
el: line,
x: 0, y: 0, vx: 0, vy: 0, life: 0
});
}
function emitSparks(intensity) {
sparkPool.forEach(spark => {
if(spark.life <= 0 && Math.random() < intensity) {
spark.x = (Math.random() * 60) - 20; // 顶部偏左区域发生切削
spark.y = -160;
spark.vx = (Math.random() * 8 + 2); // 向右飞溅
spark.vy = -(Math.random() * 6 + 2); // 向上飞溅
spark.life = 1.0;
}
if(spark.life > 0) {
spark.x += spark.vx;
spark.y += spark.vy;
spark.vy += 0.2; // 重力
spark.life -= 0.05;
spark.el.setAttribute("x1", spark.x);
spark.el.setAttribute("y1", spark.y);
spark.el.setAttribute("x2", spark.x - spark.vx);
spark.el.setAttribute("y2", spark.y - spark.vy);
spark.el.setAttribute("opacity", spark.life);
} else {
spark.el.setAttribute("opacity", "0");
}
});
}
function clearSparks() {
sparkPool.forEach(spark => {
spark.life = 0;
spark.el.setAttribute("opacity", "0");
});
}
// 核心渲染循环
function render(timestamp) {
const time = timestamp % TOTAL_DURATION;
const progress = time / TOTAL_DURATION; // 0.0 到 1.0
// 状态机变量
let topSpringY = 0;
let sideSpringY = 0;
let sideSpringX = 0;
let sideSpringTilt = 0; // 点头/翘尾角度
let wheelY = -280;
let forceOpacity = 0;
let glowOpacity = 0;
let sparkIntensity = 0;
let phaseText = "";
/*
* 时间轴分配:
* 0.0 - 0.1: 下料入孔 (Drop In)
* 0.1 - 0.2: 砂轮接近,施加磨削力 (Engage)
* 0.2 - 0.3: 【核心动作】工件被推至垂直壁面,完全贴合并强制垂直 (Lock/IFR)
* 0.3 - 0.7: 磨削过程,展示稳定性 (Grinding)
* 0.7 - 0.8: 砂轮移开,力消失,工件松脱 (Release)
* 0.8 - 1.0: 移出 (Eject & Reset)
*/
if (progress < 0.1) {
// 阶段1:落料
phaseText = "PHASE 1: 工件落入 Ø2.2 偏心大孔";
const p = progress / 0.1;
topSpringY = lerp(44, 44, p); // 初始在大孔中心
sideSpringY = lerp(-300, 0, easeInOut(p));
sideSpringX = -4; // 靠左侧大孔
sideSpringTilt = lerp(5, 2, p); // 初始无约束,存在微小倾斜
}
else if (progress < 0.2) {
// 阶段2:受力
phaseText = "PHASE 2: 砂轮切入,产生侧向切削力";
const p = (progress - 0.1) / 0.1;
topSpringY = 44;
sideSpringY = 0;
sideSpringX = -4;
sideSpringTilt = 2;
wheelY = lerp(-280, -170, easeInOut(p));
forceOpacity = lerp(0, 1, p);
}
else if (progress < 0.3) {
// 阶段3:理想解展现 (强制导向贴合)
phaseText = "PHASE 3: [IFR生效] 强制垂直面 100% 贴合,消除倾斜";
const p = (progress - 0.2) / 0.1;
// 俯视:向小孔偏移 (中心Y从44移至-40.4)
topSpringY = lerp(44, -40.4, easeInOut(p));
// 侧视:向右壁移动并消除倾斜
sideSpringY = 0;
sideSpringX = lerp(-4, 0.4, easeInOut(p)); // 0.4 是紧贴右壁的相对坐标
sideSpringTilt = lerp(2, 0, easeInOut(p));
wheelY = -170;
forceOpacity = 1;
glowOpacity = lerp(0, 1, p); // 承重墙高亮亮起
}
else if (progress < 0.7) {
// 阶段4:稳定磨削
phaseText = "PHASE 4: 零斜率强制导向磨削中...";
topSpringY = -40.4;
sideSpringY = 0;
sideSpringX = 0.4;
sideSpringTilt = 0; // 绝对垂直
wheelY = -170;
forceOpacity = 1;
// 呼吸灯效果展示理想解
glowOpacity = 0.8 + 0.2 * Math.sin(time * 0.01);
sparkIntensity = 0.5;
}
else if (progress < 0.8) {
// 阶段5:松脱
phaseText = "PHASE 5: 加工结束,侧向力解除,弹簧松脱";
const p = (progress - 0.7) / 0.1;
topSpringY = lerp(-40.4, 44, easeInOut(p));
sideSpringY = 0;
sideSpringX = lerp(0.4, -4, easeInOut(p));
sideSpringTilt = lerp(0, 2, easeInOut(p));
wheelY = lerp(-170, -280, easeInOut(p));
forceOpacity = lerp(1, 0, p);
glowOpacity = lerp(1, 0, p);
sparkIntensity = 0;
}
else {
// 阶段6:复位
phaseText = "PHASE 6: 循环复位";
const p = (progress - 0.8) / 0.2;
topSpringY = 44;
sideSpringX = -4;
sideSpringTilt = 2;
sideSpringY = lerp(0, 300, easeInOut(p)); // 向下脱落
wheelY = -280;
forceOpacity = 0;
glowOpacity = 0;
sparkIntensity = 0;
}
// --- 实际应用属性 ---
// 俯视图更新
topSpring.setAttribute('transform', `translate(0, ${topSpringY})`);
topForce.setAttribute('opacity', forceOpacity);
topWallGlow.setAttribute('opacity', glowOpacity);
// 剖视图更新
// 使用 transform-origin 为中心底部附近以模拟摇头/翘尾
sideSpring.setAttribute('transform', `translate(${sideSpringX}, ${sideSpringY}) rotate(${sideSpringTilt})`);
sideSpring.style.transformOrigin = '0px 0px'; // 相对于侧视工件自身的原点
grindingWheel.setAttribute('transform', `translate(0, ${wheelY})`);
sideForce.setAttribute('opacity', forceOpacity);
// 理想解文本与高亮
sideWallGlow.setAttribute('opacity', glowOpacity);
sideWallText.setAttribute('opacity', glowOpacity);
sideGapText.setAttribute('opacity', glowOpacity);
// 火花生成
if (sparkIntensity > 0) {
emitSparks(sparkIntensity);
} else {
clearSparks();
}
// 更新仪表盘文字
phaseReadout.textContent = phaseText;
// 持续循环
requestAnimationFrame(render);
}
// DOM 加载完成后自动无缝触发,无需用户点击
window.addEventListener('DOMContentLoaded', () => {
requestAnimationFrame(render);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
