独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TRIZ IFR - 零阻力降杆机构动画</title>
<style>
:root {
--bg-color: #060913;
--grid-color: #111a2f;
--text-main: #64748b;
--text-hl: #e2e8f0;
--accent-cyan: #0ea5e9;
--accent-green: #10b981;
--accent-red: #ef4444;
--accent-amber: #f59e0b;
--mech-base: #1e293b;
--mech-arm: #cbd5e1;
--mech-dark: #0f172a;
}
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: var(--bg-color);
display: flex;
justify-content: center;
align-items: center;
font-family: 'SF Mono', Consolas, 'Courier New', monospace;
overflow: hidden;
color: var(--text-main);
}
/* 核心要求:容器居中,尺寸足够大 */
.animation-container {
position: relative;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-width: 1600px;
max-height: 900px;
filter: drop-shadow(0 10px 30px rgba(0, 0, 0, 0.5));
}
/* 核心要求:极简、小字号说明文字,放置在边缘角落,绝对不遮挡中心动画 */
.hud-text {
font-size: 11px;
fill: var(--text-main);
letter-spacing: 1px;
user-select: none;
}
.hud-title {
font-size: 13px;
fill: var(--text-hl);
font-weight: bold;
letter-spacing: 2px;
}
.hud-value {
font-size: 12px;
fill: var(--accent-cyan);
font-weight: bold;
}
.hud-ifr-badge {
font-size: 10px;
fill: var(--accent-amber);
font-weight: bold;
}
/* SVG 元素样式 */
.glow-cyan { filter: url(#glow-cyan); }
.glow-red { filter: url(#glow-red); }
.glow-green { filter: url(#glow-green); }
.mech-stroke {
stroke: var(--mech-arm);
stroke-width: 2;
fill: none;
stroke-linecap: round;
}
.dash-circle {
stroke: rgba(255, 255, 255, 0.2);
stroke-width: 1;
fill: none;
stroke-dasharray: 4 4;
}
</style>
</head>
<body>
<div class="animation-container">
<svg viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet" id="main-svg">
<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"/>
<circle cx="0" cy="0" r="1.5" fill="#1e293b"/>
</pattern>
<pattern id="micro-grid" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(17, 26, 47, 0.4)" stroke-width="0.5"/>
</pattern>
<!-- 发光滤镜 -->
<filter id="glow-cyan" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-red" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feFlood flood-color="#ef4444" result="color"/>
<feComposite in="color" in2="blur" operator="in" result="glow"/>
<feComposite in="SourceGraphic" in2="glow" operator="over" />
</filter>
<filter id="glow-green" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feFlood flood-color="#10b981" result="color"/>
<feComposite in="color" in2="blur" operator="in" result="glow"/>
<feComposite in="SourceGraphic" in2="glow" operator="over" />
</filter>
<!-- 阴影滤镜 -->
<filter id="shadow" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="2" dy="5" stdDeviation="4" flood-opacity="0.4"/>
</filter>
<!-- 金属渐变 -->
<linearGradient id="metal-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#f8fafc" />
<stop offset="50%" stop-color="#cbd5e1" />
<stop offset="100%" stop-color="#94a3b8" />
</linearGradient>
<linearGradient id="dark-metal" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#334155" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
</defs>
<!-- 背景 -->
<rect width="100%" height="100%" fill="url(#micro-grid)"/>
<rect width="100%" height="100%" fill="url(#grid)"/>
<!-- 核心物理连线及辅助轨迹 -->
<g id="guide-lines">
<circle cx="300" cy="550" r="280" class="dash-circle"/>
<path d="M 300 550 L 300 270" class="dash-circle"/>
<path d="M 300 550 L 580 550" class="dash-circle"/>
<!-- 理想解清空区域指示 -->
<path id="ifr-zone" d="M 400 600 A 100 100 0 0 0 500 500 L 500 550 Z" fill="rgba(14, 165, 233, 0)" />
</g>
<!-- 系统部件组 (居中放大) -->
<!-- 5. 液压缓冲器 -->
<g id="buffer-assembly" transform="translate(680, 520)">
<rect x="-20" y="0" width="40" height="80" fill="var(--mech-base)" rx="4"/>
<rect id="buffer-piston" x="-10" y="-30" width="20" height="40" fill="url(#metal-grad)"/>
<path d="M -25 -30 L 25 -30" stroke="var(--mech-arm)" stroke-width="4"/>
<text x="35" y="10" class="hud-text">HYDRAULIC_BUFFER</text>
</g>
<!-- 2. 主回位拉簧 -->
<g id="spring-assembly">
<circle cx="500" cy="700" r="6" fill="var(--mech-base)" stroke="var(--text-main)" stroke-width="2"/>
<path id="spring-path" d="" fill="none" stroke="var(--accent-amber)" stroke-width="6" stroke-linejoin="round"/>
<circle id="spring-top-joint" cx="500" cy="550" r="5" fill="#fff"/>
</g>
<!-- 1. 电机与偏心凸轮 -->
<g id="motor-assembly" transform="translate(420, 600)">
<!-- 电机本体底座 -->
<rect x="-40" y="-30" width="80" height="100" fill="url(#dark-metal)" rx="8" filter="url(#shadow)"/>
<circle cx="0" cy="0" r="15" fill="#1e293b" stroke="var(--text-main)" stroke-width="2"/>
<!-- 凸轮 -->
<g id="cam-rotor" transform="rotate(0)">
<!-- 水滴形凸轮 -->
<path d="M -25 0 A 25 25 0 1 0 25 0 L 10 -90 A 10 10 0 0 0 -10 -90 Z" fill="var(--accent-cyan)" class="glow-cyan" opacity="0.9"/>
<circle cx="0" cy="0" r="6" fill="#fff"/>
<circle cx="0" cy="-75" r="4" fill="#0f172a"/>
</g>
</g>
<!-- 3. 摇臂系统 -->
<g id="rocker-assembly" transform="translate(300, 550)">
<g id="rocker-arm" transform="rotate(0)">
<!-- 摇臂主体 (总长500) -->
<rect x="0" y="-20" width="480" height="40" fill="url(#metal-grad)" rx="20" filter="url(#shadow)"/>
<!-- 锁扣槽 -->
<rect x="50" y="-25" width="20" height="15" fill="var(--bg-color)"/>
<!-- 弹簧连接点 -->
<circle cx="200" cy="0" r="6" fill="var(--mech-dark)"/>
<!-- 凸轮受力垫板 -->
<rect x="90" y="15" width="60" height="10" fill="var(--accent-amber)" rx="2"/>
<!-- 物理枢轴 -->
<circle cx="0" cy="0" r="12" fill="url(#dark-metal)" stroke="#94a3b8" stroke-width="3"/>
<circle cx="0" cy="0" r="4" fill="#fff"/>
</g>
</g>
<!-- 4. 独立电磁锁扣 (位于摇臂 90度 也就是垂直时的左侧) -->
<g id="latch-assembly" transform="translate(240, 240)">
<!-- 电磁铁外壳 -->
<rect x="-40" y="-20" width="40" height="40" fill="url(#dark-metal)" rx="4"/>
<!-- 锁舌 -->
<rect id="latch-pin" x="0" y="-6" width="30" height="12" fill="var(--mech-arm)" rx="2"/>
<!-- 状态指示灯 -->
<circle id="latch-light" cx="-20" cy="0" r="5" fill="var(--accent-amber)"/>
</g>
<!-- HUD 数据层 (布置在四角,绝不遮挡中央机构) -->
<g id="hud-layer">
<!-- 左上角:系统标题与原理说明 -->
<g transform="translate(40, 40)">
<text x="0" y="0" class="hud-title">SYSTEM_ARCHITECTURE // TRIZ IFR</text>
<text x="0" y="25" class="hud-text">MISSION: ELIMINATE BACK-DRAG RESISTANCE</text>
<text x="0" y="45" class="hud-text">SOLUTION: CAM LIFT + INDEPENDENT LATCH</text>
<rect x="0" y="55" width="300" height="1" fill="var(--grid-color)"/>
<text x="0" y="75" class="hud-ifr-badge">IFR STATE: PURE MECHANICAL FREE-FALL</text>
</g>
<!-- 右上角:实时遥测数据 -->
<g transform="translate(980, 40)">
<text x="180" y="0" class="hud-title" text-anchor="end">TELEMETRY_DATA</text>
<text x="60" y="30" class="hud-text">PHASE:</text>
<text x="180" y="30" class="hud-value" id="hud-phase" text-anchor="end">IDLE</text>
<text x="60" y="50" class="hud-text">MOTOR_CAM:</text>
<text x="180" y="50" class="hud-value" id="hud-cam-angle" text-anchor="end">0.0°</text>
<text x="60" y="70" class="hud-text">ARM_ANGLE:</text>
<text x="180" y="70" class="hud-value" id="hud-arm-angle" text-anchor="end">0.0°</text>
<text x="60" y="90" class="hud-text">LATCH_SYS:</text>
<text x="180" y="90" class="hud-value" id="hud-latch" text-anchor="end" fill="var(--accent-amber)">DISENGAGED</text>
</g>
<!-- 左下角:TRIZ 核心机制动态指示 -->
<g transform="translate(40, 720)">
<text x="0" y="0" class="hud-text" fill="var(--text-hl)">IFR MECHANISM INSIGHT:</text>
<text x="0" y="20" class="hud-text" id="hud-insight" fill="var(--accent-cyan)">MOTOR PUSHING ARM, STORING POTENTIAL ENERGY</text>
<rect x="0" y="35" width="10" height="10" fill="var(--accent-cyan)"/>
<text x="18" y="44" class="hud-text">ENERGY INPUT (CAM)</text>
<rect x="180" y="35" width="10" height="10" fill="var(--accent-amber)"/>
<text x="198" y="44" class="hud-text">POTENTIAL (SPRING)</text>
</g>
<!-- 动态 IFR 清空区域指示箭头和文字 (由JS控制透明度) -->
<g id="ifr-indicator" transform="translate(380, 650)" opacity="0">
<path d="M 0 0 L 40 -40 M 40 -40 L 40 -20 M 40 -40 L 20 -40" stroke="var(--accent-green)" stroke-width="2" fill="none" class="glow-green"/>
<text x="50" y="-35" class="hud-text" fill="var(--accent-green)" font-weight="bold">IFR: MOTOR CLEARED (ZERO DRAG)</text>
</g>
</g>
</svg>
</div>
<script>
// 动画状态与时间控制 (纯JS实现精确物理状态机)
const duration = 10000; // 10秒一个完整周期
// DOM 元素引用
const elCam = document.getElementById('cam-rotor');
const elArm = document.getElementById('rocker-arm');
const elSpringPath = document.getElementById('spring-path');
const elSpringJoint = document.getElementById('spring-top-joint');
const elLatchPin = document.getElementById('latch-pin');
const elLatchLight = document.getElementById('latch-light');
const elBufferPiston = document.getElementById('buffer-piston');
const elIfrIndicator = document.getElementById('ifr-indicator');
const elIfrZone = document.getElementById('ifr-zone');
// HUD 引用
const hudPhase = document.getElementById('hud-phase');
const hudCamAngle = document.getElementById('hud-cam-angle');
const hudArmAngle = document.getElementById('hud-arm-angle');
const hudLatch = document.getElementById('hud-latch');
const hudInsight = document.getElementById('hud-insight');
// 物理锚点坐标 (依据 SVG)
const pivotX = 300;
const pivotY = 550;
const springGroundX = 500;
const springGroundY = 700;
const springLocalX = 200; // 弹簧连接点在摇臂上的局部 X
// 缓动函数
function easeInOutSine(x) { return -(Math.cos(Math.PI * x) - 1) / 2; }
function easeInQuad(x) { return x * x; }
function easeOutBounce(x) {
const n1 = 7.5625; const d1 = 2.75;
if (x < 1 / d1) { return n1 * x * x; }
else if (x < 2 / d1) { return n1 * (x -= 1.5 / d1) * x + 0.75; }
else if (x < 2.5 / d1) { return n1 * (x -= 2.25 / d1) * x + 0.9375; }
else { return n1 * (x -= 2.625 / d1) * x + 0.984375; }
}
// 绘制锯齿状弹簧
function drawSpring(x1, y1, x2, y2, coils = 12) {
const dx = x2 - x1;
const dy = y2 - y1;
const dist = Math.sqrt(dx*dx + dy*dy);
const angle = Math.atan2(dy, dx);
const width = 15;
const step = dist / coils;
let path = `M ${x1} ${y1} `;
for (let i = 1; i <= coils; i++) {
const curDist = i * step;
const curDistPrev = (i - 0.5) * step;
// 垂直于弹簧方向的偏移
const perpX = Math.cos(angle + Math.PI/2) * (i%2===0 ? width : -width);
const perpY = Math.sin(angle + Math.PI/2) * (i%2===0 ? width : -width);
const px = x1 + Math.cos(angle) * curDistPrev + perpX;
const py = y1 + Math.sin(angle) * curDistPrev + perpY;
const nx = x1 + Math.cos(angle) * curDist;
const ny = y1 + Math.sin(angle) * curDist;
path += `L ${px} ${py} L ${nx} ${ny} `;
}
return path;
}
let startTime = performance.now();
function renderFrame(time) {
let elapsed = (time - startTime) % duration;
let t = elapsed / duration; // 0.0 到 1.0
let camAngle = 0;
let armAngle = 0;
let latchPos = 0; // 0: 缩回, 1: 伸出
let latchColor = 'var(--accent-amber)';
let bufferSquish = 0;
let phaseName = "";
let insightMsg = "";
// 状态机逻辑
// 0.00 - 0.05: 待机
if (t < 0.05) {
phaseName = "IDLE";
insightMsg = "SYSTEM READY - WAITING FOR LIFT COMMAND";
camAngle = 0;
armAngle = 0;
}
// 0.05 - 0.35: 顶升阶段 (凸轮推摇臂至 -90度)
else if (t < 0.35) {
let p = (t - 0.05) / 0.30;
p = easeInOutSine(p);
phaseName = "LIFTING (ENERGY STORE)";
insightMsg = "MOTOR DRIVES CAM, CONVERTING KINETIC TO POTENTIAL ENERGY";
camAngle = p * 180;
armAngle = p * -90;
}
// 0.35 - 0.40: 锁扣卡死
else if (t < 0.40) {
let p = (t - 0.35) / 0.05;
phaseName = "LOCKING";
insightMsg = "LATCH ENGAGES. POTENTIAL ENERGY IS SECURED.";
camAngle = 180;
armAngle = -90;
latchPos = p;
latchColor = 'var(--accent-green)';
}
// 0.40 - 0.65: 电机继续旋转至避让位 (IFR 核心)
else if (t < 0.65) {
let p = (t - 0.40) / 0.25;
p = easeInOutSine(p);
phaseName = "MOTOR CLEARANCE (IFR)";
insightMsg = "CRITICAL: MOTOR MOVES AWAY. 0 DRAG PATH CLEARED.";
camAngle = 180 + p * 180;
armAngle = -90;
latchPos = 1;
latchColor = 'var(--accent-green)';
}
// 0.65 - 0.70: 准备释放
else if (t < 0.70) {
phaseName = "HOLDING / ARMED";
insightMsg = "IFR STATE ACHIEVED. WAITING FOR DROP SIGNAL.";
camAngle = 360;
armAngle = -90;
latchPos = 1;
latchColor = 'var(--accent-green)';
}
// 0.70 - 0.72: 电磁铁失电松开
else if (t < 0.72) {
let p = (t - 0.70) / 0.02;
phaseName = "RELEASE TRIGGERED";
insightMsg = "LATCH RELEASES WITH MINIMAL CONTROL ENERGY.";
camAngle = 360;
armAngle = -90;
latchPos = 1 - p;
latchColor = 'var(--accent-red)';
}
// 0.72 - 0.76: 瞬间无阻力坠落
else if (t < 0.76) {
let p = (t - 0.72) / 0.04;
p = easeInQuad(p);
phaseName = "FREE-FALL (ZERO DRAG)";
insightMsg = "PURE GRAVITY + SPRING FORCE. NO MOTOR FRICTION.";
camAngle = 360;
armAngle = -90 + p * 90;
latchPos = 0;
latchColor = 'var(--accent-red)';
}
// 0.76 - 0.85: 液压缓冲
else if (t < 0.85) {
let p = (t - 0.76) / 0.09;
p = easeOutBounce(p);
phaseName = "ENERGY ABSORPTION";
insightMsg = "HYDRAULIC BUFFER ABSORBS KINETIC IMPACT.";
camAngle = 360;
// 模拟反弹
let bounce = Math.sin(p * Math.PI) * (1-p) * -5;
armAngle = bounce;
bufferSquish = Math.sin(p * Math.PI) * (1-p) * 20;
latchPos = 0;
latchColor = 'var(--accent-amber)';
}
// 0.85 - 1.00: 稳定与重置
else {
phaseName = "CYCLE COMPLETE";
insightMsg = "SYSTEM RESET TO INITIAL STATE.";
camAngle = 360;
armAngle = 0;
latchPos = 0;
latchColor = 'var(--accent-amber)';
}
// --- DOM 更新 ---
// 1. 旋转更新
elCam.setAttribute('transform', `rotate(${camAngle})`);
elArm.setAttribute('transform', `rotate(${armAngle})`);
// 2. 锁扣更新 (向右伸出 30px)
elLatchPin.setAttribute('transform', `translate(${latchPos * 25}, 0)`);
elLatchLight.setAttribute('fill', latchColor);
// 3. 缓冲器更新
elBufferPiston.setAttribute('y', -30 + bufferSquish);
// 4. 计算弹簧连接点世界坐标并绘制弹簧
// 摇臂初始水平时,连接点在相对于枢轴 dx = 200, dy = 0
const armRad = armAngle * Math.PI / 180;
const jx = pivotX + springLocalX * Math.cos(armRad);
const jy = pivotY + springLocalX * Math.sin(armRad);
elSpringJoint.setAttribute('cx', jx);
elSpringJoint.setAttribute('cy', jy);
elSpringPath.setAttribute('d', drawSpring(springGroundX, springGroundY, jx, jy));
// 根据弹簧拉伸长度调整颜色亮度 (物理张力可视化)
const currentLen = Math.sqrt((jx-springGroundX)**2 + (jy-springGroundY)**2);
const minLen = Math.sqrt((pivotX+springLocalX-springGroundX)**2 + (pivotY-springGroundY)**2);
const tension = Math.min(1, Math.max(0, (currentLen - minLen) / 250));
elSpringPath.setAttribute('stroke', `rgb(245, ${158 - tension*100}, ${11 + tension*50})`);
// 5. IFR 视觉引导特效 (当电机离开,突出展示下方无阻挡)
if (t > 0.45 && t < 0.70) {
elIfrIndicator.setAttribute('opacity', Math.min(1, (t - 0.45) * 5));
elIfrZone.setAttribute('fill', 'rgba(16, 185, 129, 0.1)'); // 绿色幽光
} else {
elIfrIndicator.setAttribute('opacity', 0);
elIfrZone.setAttribute('fill', 'rgba(14, 165, 233, 0)');
}
// 6. HUD 文字更新
hudPhase.textContent = phaseName;
hudInsight.textContent = insightMsg;
hudCamAngle.textContent = (camAngle % 360).toFixed(1) + '°';
hudArmAngle.textContent = armAngle.toFixed(1) + '°';
if (latchPos === 1) {
hudLatch.textContent = "LOCKED (SECURE)";
hudLatch.setAttribute('fill', 'var(--accent-green)');
} else if (latchPos === 0) {
hudLatch.textContent = "DISENGAGED";
hudLatch.setAttribute('fill', 'var(--accent-amber)');
} else {
hudLatch.textContent = "ACTUATING...";
hudLatch.setAttribute('fill', 'var(--accent-red)');
}
requestAnimationFrame(renderFrame);
}
// 自动触发循环动画 (重开即播,符合要求)
requestAnimationFrame(renderFrame);
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
