独立渲染引擎就绪引擎就绪
<!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>
<style>
:root {
--bg-color: #07090f;
--grid-color: rgba(255, 255, 255, 0.04);
--accent-cyan: #00f0ff;
--accent-orange: #ff5500;
--accent-blue: #3a86ff;
--panel-bg: rgba(10, 14, 23, 0.85);
--text-main: #e2e8f0;
--text-muted: #64748b;
}
body {
margin: 0;
padding: 0;
background-color: var(--bg-color);
color: var(--text-main);
font-family: 'SF Pro Display', -apple-system, 'Segoe UI', Roboto, Helvetica, sans-serif;
overflow: hidden;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-image:
radial-gradient(circle at center, #111827 0%, #000000 100%),
linear-gradient(0deg, var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
background-blend-mode: overlay;
}
/* 绝对遵循:精简且极小的角落文字说明,不遮挡中央 */
.hud-corner {
position: absolute;
z-index: 100;
background: var(--panel-bg);
border: 1px solid rgba(255, 255, 255, 0.1);
padding: 12px 16px;
border-radius: 6px;
backdrop-filter: blur(10px);
pointer-events: none;
max-width: 280px;
}
.top-left { top: 20px; left: 20px; border-left: 3px solid var(--accent-cyan); }
.bottom-right { bottom: 20px; right: 20px; border-right: 3px solid var(--accent-orange); text-align: right; }
.hud-title {
font-size: 13px;
font-weight: 700;
margin: 0 0 4px 0;
color: #fff;
letter-spacing: 1px;
}
.hud-desc {
font-size: 11px;
color: var(--text-muted);
margin: 0;
line-height: 1.5;
}
.status-badge {
display: inline-block;
font-family: monospace;
font-size: 11px;
padding: 3px 8px;
background: rgba(255,255,255,0.05);
border-radius: 3px;
color: var(--accent-cyan);
margin-top: 6px;
}
#timer-bar-container {
width: 100%;
height: 2px;
background: rgba(255,255,255,0.1);
margin-top: 8px;
border-radius: 1px;
overflow: hidden;
}
#timer-bar {
height: 100%;
width: 0%;
background: var(--accent-cyan);
transition: width 0.1s linear;
}
/* SVG 动画容器,确保充分居中且足够大 */
.svg-container {
position: relative;
width: 90vmin;
height: 90vmin;
max-width: 1000px;
max-height: 1000px;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
overflow: visible;
}
/* 核心部件过渡效果 */
#rotary-table {
transform-origin: 0 0;
/* JS 动态控制 transform,此处设定平滑贝塞尔曲线表现机械旋转的惯性 */
transition: transform 2.5s cubic-bezier(0.65, 0, 0.35, 1);
}
#pressure-beam {
transition: transform 1s cubic-bezier(0.4, 0, 0.2, 1);
}
.workpiece {
transition: fill 1s;
}
/* 呼吸光效与动作态 */
@keyframes pulse-cyan {
0%, 100% { opacity: 0.2; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.05); }
}
@keyframes cool-down {
0% { opacity: 0.8; fill: #60a5fa; }
100% { opacity: 0.1; fill: #1e3a8a; }
}
.loading-aura {
animation: pulse-cyan 2s infinite ease-in-out;
transform-origin: center;
}
.cooling-aura {
transition: opacity 1s, fill 4s linear;
}
</style>
</head>
<body>
<!-- 左上角极简说明 -->
<div class="hud-corner top-left">
<h1 class="hud-title">TRIZ 理想解 (IFR)</h1>
<p class="hud-desc">原直线工域转换为环形二维工域。巧妙利用回转支撑空间,通过 120° 分度实现装配、焊接、冷却三工位并行无缝协同,消除空间与时间冲突。</p>
</div>
<!-- 右下角极简状态监控 -->
<div class="hud-corner bottom-right">
<h1 class="hud-title">系统实时状态监控</h1>
<p class="hud-desc" id="status-text">初始化...</p>
<div class="status-badge" id="status-phase">PHASE 00</div>
<div id="timer-bar-container"><div id="timer-bar"></div></div>
</div>
<!-- 中央核心动画区 -->
<div class="svg-container">
<svg viewBox="-500 -500 1000 1000">
<defs>
<!-- 滤镜与发光效果 -->
<filter id="glow-orange" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="8" result="blur1" />
<feGaussianBlur stdDeviation="15" result="blur2" />
<feMerge>
<feMergeNode in="blur2" />
<feMergeNode in="blur1" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 材质渐变 -->
<radialGradient id="metal-base" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#2a303c" />
<stop offset="80%" stop-color="#151922" />
<stop offset="100%" stop-color="#0b0f19" />
</radialGradient>
<linearGradient id="metal-frame" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#475569" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 轨道纹理 -->
<pattern id="track-pattern" width="20" height="20" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" y1="0" x2="0" y2="20" stroke="rgba(255,255,255,0.05)" stroke-width="2"/>
</pattern>
</defs>
<!-- 底层背景环境环 -->
<g id="environment" stroke="rgba(255,255,255,0.1)" stroke-width="1" fill="none">
<circle cx="0" cy="0" r="450" stroke-dasharray="4 8" />
<circle cx="0" cy="0" r="400" />
<!-- 120度工位分割引导线 -->
<line x1="0" y1="0" x2="0" y2="-450" stroke="rgba(255,255,255,0.2)" />
<line x1="0" y1="0" x2="389.7" y2="225" stroke="rgba(255,255,255,0.2)" />
<line x1="0" y1="0" x2="-389.7" y2="225" stroke="rgba(255,255,255,0.2)" />
</g>
<!-- 静态工位标识 (极简) -->
<g font-size="12" fill="var(--text-muted)" font-family="monospace" letter-spacing="2" text-anchor="middle">
<!-- 焊接区 (上方 -90°) -->
<text x="0" y="-465" fill="var(--accent-orange)">[ ST-2: WELDING / 焊接作业区 ]</text>
<!-- 冷却区 (右下 30°) -->
<text x="360" y="270" fill="var(--accent-blue)">[ ST-3: COOLING / 冷却下料 ]</text>
<!-- 装配区 (左下 150°) -->
<text x="-360" y="270" fill="var(--accent-cyan)">[ ST-1: ASSEMBLY / 装配上料 ]</text>
</g>
<!-- 旋转分度盘核心结构 -->
<g id="rotary-table">
<!-- 盘底 -->
<circle cx="0" cy="0" r="350" fill="url(#metal-base)" stroke="#334155" stroke-width="4"/>
<circle cx="0" cy="0" r="330" fill="url(#track-pattern)" />
<circle cx="0" cy="0" r="100" fill="#1e293b" stroke="#00f0ff" stroke-width="1" stroke-dasharray="5 5"/>
<!-- 中心转轴 -->
<circle cx="0" cy="0" r="30" fill="#cbd5e1" />
<circle cx="0" cy="0" r="15" fill="#0f172a" />
<!-- 120度隔离支架 -->
<path d="M 0 0 L 0 -350" stroke="#0f172a" stroke-width="12" stroke-linecap="round"/>
<path d="M 0 0 L 303.1 175" stroke="#0f172a" stroke-width="12" stroke-linecap="round"/>
<path d="M 0 0 L -303.1 175" stroke="#0f172a" stroke-width="12" stroke-linecap="round"/>
<!-- 随动钣金件 (3块) -->
<!-- 钣金件 1 -->
<g transform="rotate(-90) translate(220, 0) rotate(90)">
<rect class="workpiece" id="wp-1" x="-80" y="-50" width="160" height="100" rx="10" fill="#94a3b8" stroke="#cbd5e1" stroke-width="2"/>
<rect x="-60" y="-30" width="120" height="60" rx="5" fill="#64748b" />
<!-- 焊缝路径 -->
<line x1="-50" y1="0" x2="50" y2="0" stroke="#334155" stroke-width="2" stroke-dasharray="4 2"/>
</g>
<!-- 钣金件 2 -->
<g transform="rotate(30) translate(220, 0) rotate(-30)">
<rect class="workpiece" id="wp-2" x="-80" y="-50" width="160" height="100" rx="10" fill="#94a3b8" stroke="#cbd5e1" stroke-width="2"/>
<rect x="-60" y="-30" width="120" height="60" rx="5" fill="#64748b" />
<line x1="-50" y1="0" x2="50" y2="0" stroke="#334155" stroke-width="2" stroke-dasharray="4 2"/>
</g>
<!-- 钣金件 3 -->
<g transform="rotate(150) translate(220, 0) rotate(-150)">
<rect class="workpiece" id="wp-3" x="-80" y="-50" width="160" height="100" rx="10" fill="#94a3b8" stroke="#cbd5e1" stroke-width="2"/>
<rect x="-60" y="-30" width="120" height="60" rx="5" fill="#64748b" />
<line x1="-50" y1="0" x2="50" y2="0" stroke="#334155" stroke-width="2" stroke-dasharray="4 2"/>
</g>
</g>
<!-- === 静态工位工作效果层 (不随盘旋转) === -->
<!-- ST-1 装配区光效 (左下) -->
<g id="fx-assembly" transform="rotate(150) translate(220, 0) rotate(-150)" opacity="0">
<rect x="-90" y="-60" width="180" height="120" rx="15" fill="none" stroke="var(--accent-cyan)" stroke-width="3" stroke-dasharray="10 5" class="loading-aura"/>
<path d="M -20 -80 L 0 -50 L 20 -80 Z" fill="var(--accent-cyan)" opacity="0.8">
<animate attributeName="transform" values="translate(0, -10); translate(0, 0); translate(0, -10)" dur="1s" repeatCount="indefinite" />
</path>
</g>
<!-- ST-3 冷却区光效 (右下) -->
<g id="fx-cooling" transform="rotate(30) translate(220, 0) rotate(-30)" opacity="0">
<rect x="-85" y="-55" width="170" height="110" rx="12" fill="var(--accent-blue)" class="cooling-aura" opacity="0.3" filter="url(#glow-cyan)"/>
<!-- 散发的热气动画将在 JS 中生成 -->
</g>
<!-- ST-2 焊接区与压力架 (上方) -->
<g id="fx-welding">
<!-- 重载压力架桥墩 (两侧) -->
<rect x="-160" y="-320" width="40" height="100" rx="5" fill="url(#metal-frame)" stroke="#0f172a" stroke-width="2"/>
<rect x="120" y="-320" width="40" height="100" rx="5" fill="url(#metal-frame)" stroke="#0f172a" stroke-width="2"/>
<!-- 动态升降压力架横梁 -->
<g id="pressure-beam" transform="translate(0, 0)">
<!-- 横梁主体 -->
<rect x="-180" y="-300" width="360" height="40" rx="8" fill="url(#metal-frame)" stroke="#475569" stroke-width="1"/>
<!-- 压紧气缸/液压杆 -->
<rect x="-100" y="-260" width="20" height="40" fill="#94a3b8" />
<rect x="80" y="-260" width="20" height="40" fill="#94a3b8" />
<!-- 压紧触头 -->
<path d="M -115 -220 L -85 -220 L -90 -200 L -110 -200 Z" fill="#b91c1c" />
<path d="M 85 -220 L 115 -220 L 110 -200 L 90 -200 Z" fill="#b91c1c" />
<!-- 自动焊枪头 -->
<rect x="-15" y="-260" width="30" height="30" fill="#334155" />
<path d="M -5 -230 L 5 -230 L 2 -200 L -2 -200 Z" fill="#eab308" />
</g>
<!-- 焊接火花粒子容器 -->
<g id="spark-container"></g>
</g>
<!-- 坐标辅助十字线 (最上层细线) -->
<path d="M 0 -80 L 0 80 M -80 0 L 80 0" stroke="rgba(255,255,255,0.15)" stroke-width="1" />
</svg>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
// DOM 元素引用
const rotaryTable = document.getElementById('rotary-table');
const pressureBeam = document.getElementById('pressure-beam');
const sparkContainer = document.getElementById('spark-container');
const fxAssembly = document.getElementById('fx-assembly');
const fxCooling = document.getElementById('fx-cooling');
const coolingAura = fxCooling.querySelector('.cooling-aura');
const statusText = document.getElementById('status-text');
const statusPhase = document.getElementById('status-phase');
const timerBar = document.getElementById('timer-bar');
// 核心参数设定
let currentAngle = 0;
let sparkInterval = null;
let timerInterval = null;
// 状态机时序定义 (毫秒)
const timings = {
work: 4000, // 装配、焊接、冷却并行作业时间
lift: 1000, // 焊接结束,压力架抬起时间
rotate: 2000, // 回转盘120度旋转时间 (<15s的理想化极速展示)
press: 1000 // 旋转到位,压力架下压锁紧时间
};
// 辅助:进度条控制
function startTimerBar(duration) {
clearInterval(timerInterval);
timerBar.style.transition = 'none';
timerBar.style.width = '0%';
// 强制重绘
void timerBar.offsetWidth;
timerBar.style.transition = `width ${duration}ms linear`;
timerBar.style.width = '100%';
}
// 辅助:火花粒子生成器 (仅在焊接阶段激活)
function createSpark() {
const spark = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// 焊枪位置近似 (0, -200)
const startX = (Math.random() - 0.5) * 10;
const startY = -200;
spark.setAttribute("cx", startX);
spark.setAttribute("cy", startY);
spark.setAttribute("r", Math.random() * 2 + 1);
spark.setAttribute("fill", Math.random() > 0.5 ? "#fbbf24" : "#ffedd5");
spark.setAttribute("filter", "url(#glow-orange)");
sparkContainer.appendChild(spark);
// 物理抛射动画
const angle = (Math.random() * Math.PI) - (Math.PI / 2); // 向上和两侧飞散
const velocity = Math.random() * 80 + 40;
const tx = startX + Math.sin(angle) * velocity;
const ty = startY - Math.cos(angle) * velocity;
const anim = spark.animate([
{ transform: `translate(0px, 0px) scale(1)`, opacity: 1 },
{ transform: `translate(${tx}px, ${ty + 50}px) scale(0)`, opacity: 0 }
], {
duration: Math.random() * 500 + 300,
easing: 'cubic-bezier(0.25, 1, 0.5, 1)',
fill: 'forwards'
});
anim.onfinish = () => spark.remove();
}
function startSparks() {
if (sparkInterval) return;
sparkInterval = setInterval(() => {
for(let i=0; i<3; i++) createSpark();
}, 30);
}
function stopSparks() {
clearInterval(sparkInterval);
sparkInterval = null;
}
// 模拟冷却站烟雾
function createSteam() {
const steam = document.createElementNS("http://www.w3.org/2000/svg", "circle");
steam.setAttribute("cx", (Math.random() - 0.5) * 80);
steam.setAttribute("cy", (Math.random() - 0.5) * 40 - 20);
steam.setAttribute("r", Math.random() * 10 + 5);
steam.setAttribute("fill", "#60a5fa");
steam.setAttribute("opacity", "0.4");
steam.setAttribute("filter", "url(#glow-cyan)");
fxCooling.appendChild(steam);
const anim = steam.animate([
{ transform: `translate(0px, 0px) scale(1)`, opacity: 0.4 },
{ transform: `translate(${(Math.random() - 0.5)*50}px, -100px) scale(3)`, opacity: 0 }
], {
duration: 2000,
easing: 'linear',
fill: 'forwards'
});
anim.onfinish = () => steam.remove();
}
let steamInterval = null;
// ================= 核心状态机动画循环 =================
async function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function runCycle() {
// [ PHASE 1: 锁紧与并行作业 ]
statusPhase.innerText = "PHASE 01: 并行作业";
statusText.innerHTML = "压力架已锁紧<br/>装配、焊接、冷却三工位同时运行中";
statusText.style.color = "var(--accent-cyan)";
startTimerBar(timings.work);
// UI 表现
pressureBeam.style.transform = "translate(0, 0)"; // 下压锁紧态
fxAssembly.style.opacity = "1";
fxCooling.style.opacity = "1";
coolingAura.style.fill = "#60a5fa"; // 初始高温
coolingAura.style.opacity = "0.8";
startSparks();
steamInterval = setInterval(createSteam, 200);
// 模拟冷却过程的颜色渐变
setTimeout(() => {
coolingAura.style.fill = "#1e3a8a";
coolingAura.style.opacity = "0.1";
}, 100);
await wait(timings.work);
// [ PHASE 2: 动作完成,解脱干涉 ]
statusPhase.innerText = "PHASE 02: 机构解脱";
statusText.innerHTML = "本节拍动作完成,焊接停止<br/>发出信号,压力架自动微抬起避让";
statusText.style.color = "var(--accent-orange)";
startTimerBar(timings.lift);
// UI 表现
stopSparks();
clearInterval(steamInterval);
fxAssembly.style.opacity = "0";
fxCooling.style.opacity = "0";
pressureBeam.style.transform = "translate(0, -60px)"; // 向上抬起60px
await wait(timings.lift);
// [ PHASE 3: 回转盘分度旋转 ]
statusPhase.innerText = "PHASE 03: 分度切换";
statusText.innerHTML = "回转盘快速旋转 120°<br/>工件平滑流转至下一工位";
statusText.style.color = "var(--text-main)";
startTimerBar(timings.rotate);
// UI 表现
currentAngle += 120;
rotaryTable.style.transform = `rotate(${currentAngle}deg)`;
await wait(timings.rotate);
// [ PHASE 4: 到位锁紧 ]
statusPhase.innerText = "PHASE 04: 定位锁紧";
statusText.innerHTML = "到达 120° 预定工位,机械定位<br/>压力架下压锁紧,准备进入下一节拍";
statusText.style.color = "var(--text-muted)";
startTimerBar(timings.press);
// UI 表现
pressureBeam.style.transform = "translate(0, 0)"; // 再次下压
await wait(timings.press);
// 循环迭代
requestAnimationFrame(runCycle);
}
// 初始化后稍微延迟启动,让用户看清初始状态
setTimeout(runCycle, 500);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
