独立渲染引擎就绪引擎就绪
<!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>
/* CSS Variables for Bold Cyber-Industrial Aesthetic */
:root {
--bg-base: #020617; /* Very dark slate */
--bg-grid: #1e293b;
--accent-cyan: #06b6d4;
--accent-amber: #f59e0b;
--accent-rose: #e11d48;
--text-main: #94a3b8;
--text-bright: #f8fafc;
--hud-bg: rgba(2, 6, 23, 0.75);
--hud-border: rgba(6, 182, 212, 0.3);
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}
body, html {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
background-color: var(--bg-base);
color: var(--text-main);
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
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;
}
/* Subtle radial vignette to focus center */
body::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: radial-gradient(circle at center, transparent 30%, var(--bg-base) 100%);
pointer-events: none;
z-index: 0;
}
#animation-container {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}
svg {
width: 100%;
height: 100%;
max-width: 900px;
max-height: 900px;
filter: drop-shadow(0 0 20px rgba(6, 182, 212, 0.1));
}
/* UI HUD Elements - Strictly confined to edges, small font */
.hud-panel {
position: absolute;
background: var(--hud-bg);
border: 1px solid var(--hud-border);
padding: 12px 16px;
border-radius: 4px;
backdrop-filter: blur(8px);
font-size: 12px;
z-index: 10;
display: flex;
flex-direction: column;
gap: 8px;
}
.hud-top-left { top: 20px; left: 20px; }
.hud-top-right { top: 20px; right: 20px; text-align: right; }
.hud-bottom-left { bottom: 20px; left: 20px; width: 280px; }
.hud-bottom-right { bottom: 20px; right: 20px; }
.hud-title {
color: var(--text-bright);
font-size: 14px;
font-weight: bold;
letter-spacing: 2px;
margin-bottom: 4px;
border-bottom: 1px solid var(--hud-border);
padding-bottom: 4px;
}
.data-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.data-label { color: var(--text-main); }
.data-value {
color: var(--accent-cyan);
font-weight: bold;
font-variant-numeric: tabular-nums;
}
.data-value.amber { color: var(--accent-amber); }
.data-value.rose { color: var(--accent-rose); }
/* Custom Slider */
input[type=range] {
-webkit-appearance: none;
width: 100%;
background: transparent;
margin-top: 8px;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: rgba(6, 182, 212, 0.2);
border-radius: 2px;
}
input[type=range]::-webkit-slider-thumb {
height: 14px;
width: 8px;
border-radius: 2px;
background: var(--accent-cyan);
cursor: pointer;
-webkit-appearance: none;
margin-top: -5px;
box-shadow: 0 0 10px var(--accent-cyan);
}
/* Legend dots */
.legend-item { display: flex; align-items: center; gap: 6px; }
.dot { width: 8px; height: 8px; border-radius: 50%; }
.dot.cyan { background: var(--accent-cyan); box-shadow: 0 0 8px var(--accent-cyan); }
.dot.amber { background: var(--accent-amber); box-shadow: 0 0 8px var(--accent-amber); }
.dot.rose { background: var(--accent-rose); box-shadow: 0 0 8px var(--accent-rose); }
</style>
</head>
<body>
<div id="animation-container">
<!-- SVG Canvas (Center stage, unoccluded) -->
<svg viewBox="-400 -400 800 800" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- Glow Filters for Neon aesthetic -->
<filter id="glow-cyan" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<filter id="glow-amber" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<filter id="glow-rose" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="5" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<radialGradient id="sun-bg" cx="50%" cy="50%" r="50%">
<stop offset="60%" stop-color="#0f172a" />
<stop offset="100%" stop-color="#1e293b" />
</radialGradient>
</defs>
<!-- Background subtle rings -->
<circle cx="0" cy="0" r="280" fill="none" stroke="#1e293b" stroke-width="1" stroke-dasharray="4 8" />
<circle cx="0" cy="0" r="160" fill="none" stroke="#1e293b" stroke-width="1" />
<!-- Electromagnetic Stator Array (Outer) -->
<g id="stator-group"></g>
<!-- Magnetic Flux Lines (TRIZ Resource Utilization Visualization) -->
<g id="flux-lines"></g>
<!-- Flexible Ring Gear (Flexspline - Middle) -->
<!-- The deformation is driven by magnetic pull, meshing at the minor axis -->
<g id="flexspline-group">
<!-- Inner teeth representation -->
<path id="flexspline-teeth" fill="none" stroke="var(--accent-amber)" stroke-width="8" stroke-dasharray="4 6" opacity="0.6"/>
<!-- Outer ring body -->
<path id="flexspline-body" fill="none" stroke="var(--accent-amber)" stroke-width="4" filter="url(#glow-amber)"/>
</g>
<!-- Mesh Zone Highlights (Visual Guidance) -->
<g id="mesh-highlights">
<path id="mesh-top" d="M -20 -158 A 160 160 0 0 1 20 -158" fill="none" stroke="var(--accent-rose)" stroke-width="6" filter="url(#glow-rose)" stroke-linecap="round" opacity="0"/>
<path id="mesh-bot" d="M -20 158 A 160 160 0 0 0 20 158" fill="none" stroke="var(--accent-rose)" stroke-width="6" filter="url(#glow-rose)" stroke-linecap="round" opacity="0"/>
</g>
<!-- Rigid Sun Gear (Inner Core) -->
<g id="sun-gear-group">
<circle cx="0" cy="0" r="150" fill="url(#sun-bg)" stroke="#334155" stroke-width="2"/>
<path id="sun-gear-teeth" fill="none" stroke="var(--accent-rose)" stroke-width="6" />
<!-- Core geometric design -->
<circle cx="0" cy="0" r="30" fill="none" stroke="var(--accent-rose)" stroke-width="2" filter="url(#glow-rose)"/>
<path d="M -150 0 L 150 0 M 0 -150 L 0 150" stroke="#334155" stroke-width="1" stroke-dasharray="10 10"/>
<polygon points="0,-40 8,-10 40,0 8,10 0,40 -8,10 -40,0 -8,-10" fill="var(--accent-rose)" opacity="0.1"/>
</g>
</svg>
<!-- HUD Elements -->
<div class="hud-panel hud-top-left">
<div class="hud-title">IFR: 电磁虚拟行星架</div>
<div class="legend-item"><div class="dot cyan"></div>电磁定子阵列 (波发生器)</div>
<div class="legend-item"><div class="dot amber"></div>柔性环形齿圈 (柔轮)</div>
<div class="legend-item"><div class="dot rose"></div>刚性圆柱太阳轮 (输出)</div>
</div>
<div class="hud-panel hud-top-right">
<div class="hud-title">系统状态监控</div>
<div class="data-row">
<span class="data-label">变形波转速 Nw:</span>
<span class="data-value" id="val-wave-rpm">0 RPM</span>
</div>
<div class="data-row">
<span class="data-label">柔轮转速 Nf:</span>
<span class="data-value amber">0 RPM (固定)</span>
</div>
<div class="data-row">
<span class="data-label">太阳轮输出 Ns:</span>
<span class="data-value rose" id="val-sun-rpm">0 RPM</span>
</div>
</div>
<div class="hud-panel hud-bottom-left">
<div class="hud-title">交互控制 (相序换相频率)</div>
<div class="data-row">
<span class="data-label">磁场旋转频率:</span>
<span class="data-value" id="val-freq">1.0 Hz</span>
</div>
<input type="range" id="freq-slider" min="-3" max="3" step="0.1" value="1">
<div style="font-size: 10px; color: var(--text-main); margin-top: 4px;">*调节定子电流相序改变变形波公转方向与速度,实现无级调速及反转。</div>
</div>
<div class="hud-panel hud-bottom-right" style="max-width: 250px;">
<div class="hud-title">TRIZ 创新原理解析</div>
<div style="color: var(--text-main); line-height: 1.4;">
<b style="color:var(--accent-cyan)">消除机械间隙:</b>无实体行星轮,由电磁径向拉力驱动柔轮形变生成虚拟行星架。<br>
<b style="color:var(--accent-rose)">动态空间啮合:</b>长轴端受磁吸外凸,短轴端径向收缩与太阳轮无回差啮合。
</div>
</div>
</div>
<script>
// System Constants & Geometries
const R_SUN = 156; // Outer radius of sun gear
const R_FLEX_BASE = 190; // Base radius of unstretched flexspline
const DEFORMATION_AMP = 34; // Radial deformation (R_FLEX_BASE - AMP = R_SUN) ensures meshing at minor axis
const R_STATOR_INNER = 250;
const R_STATOR_OUTER = 280;
const STATOR_COUNT = 24;
const GEAR_TEETH_SUN = 60;
const GEAR_RATIO = -0.05; // Simplified ratio: Sun gear moves opposite and slower than wave
// State Variables
let waveAngle = 0; // Current angle of the magnetic wave (radians)
let sunAngle = 0; // Current angle of the sun gear (radians)
let waveSpeed = 0.02; // Base animation speed (controlled by slider)
// DOM Elements
const statorGroup = document.getElementById('stator-group');
const fluxLinesGroup = document.getElementById('flux-lines');
const flexBody = document.getElementById('flexspline-body');
const flexTeeth = document.getElementById('flexspline-teeth');
const sunGearGroup = document.getElementById('sun-gear-group');
const sunGearTeeth = document.getElementById('sun-gear-teeth');
const meshTop = document.getElementById('mesh-top');
const meshBot = document.getElementById('mesh-bot');
const slider = document.getElementById('freq-slider');
// Initialization: Build Static Geometries
function initGeometry() {
// 1. Build Stators
for (let i = 0; i < STATOR_COUNT; i++) {
const angle = (i / STATOR_COUNT) * Math.PI * 2;
const cx1 = Math.cos(angle) * R_STATOR_INNER;
const cy1 = Math.sin(angle) * R_STATOR_INNER;
const cx2 = Math.cos(angle) * R_STATOR_OUTER;
const cy2 = Math.sin(angle) * R_STATOR_OUTER;
// Stator coil block
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
// Calculate corner points for the stator trapezoid
const a1 = angle - 0.08;
const a2 = angle + 0.08;
const d = `M ${Math.cos(a1)*R_STATOR_INNER} ${Math.sin(a1)*R_STATOR_INNER}
L ${Math.cos(a1)*R_STATOR_OUTER} ${Math.sin(a1)*R_STATOR_OUTER}
A ${R_STATOR_OUTER} ${R_STATOR_OUTER} 0 0 1 ${Math.cos(a2)*R_STATOR_OUTER} ${Math.sin(a2)*R_STATOR_OUTER}
L ${Math.cos(a2)*R_STATOR_INNER} ${Math.sin(a2)*R_STATOR_INNER} Z`;
path.setAttribute("d", d);
path.setAttribute("fill", "var(--bg-grid)");
path.setAttribute("stroke", "#334155");
path.setAttribute("stroke-width", "1");
path.id = `stator-${i}`;
statorGroup.appendChild(path);
// Flux line container
const flux = document.createElementNS("http://www.w3.org/2000/svg", "path");
flux.id = `flux-${i}`;
flux.setAttribute("fill", "none");
flux.setAttribute("stroke", "var(--accent-cyan)");
flux.setAttribute("stroke-width", "2");
flux.setAttribute("stroke-dasharray", "4 4");
flux.style.opacity = 0;
fluxLinesGroup.appendChild(flux);
}
// 2. Build Sun Gear Teeth (Static path, group rotates)
let sunPath = "";
for (let i = 0; i < GEAR_TEETH_SUN; i++) {
const a1 = (i / GEAR_TEETH_SUN) * Math.PI * 2;
const a2 = ((i + 0.4) / GEAR_TEETH_SUN) * Math.PI * 2;
const a3 = ((i + 0.6) / GEAR_TEETH_SUN) * Math.PI * 2;
const a4 = ((i + 1) / GEAR_TEETH_SUN) * Math.PI * 2;
const rOut = R_SUN;
const rIn = R_SUN - 8;
sunPath += i === 0 ? `M ${Math.cos(a1)*rIn} ${Math.sin(a1)*rIn} ` : `L ${Math.cos(a1)*rIn} ${Math.sin(a1)*rIn} `;
sunPath += `L ${Math.cos(a2)*rOut} ${Math.sin(a2)*rOut} `;
sunPath += `L ${Math.cos(a3)*rOut} ${Math.sin(a3)*rOut} `;
sunPath += `L ${Math.cos(a4)*rIn} ${Math.sin(a4)*rIn} `;
}
sunPath += "Z";
sunGearTeeth.setAttribute("d", sunPath);
}
// Core Animation Loop
function animate() {
// Update Angles
waveAngle += waveSpeed;
sunAngle += waveSpeed * GEAR_RATIO;
// Normalize angles for display
if (waveAngle >= Math.PI * 2) waveAngle -= Math.PI * 2;
if (waveAngle < 0) waveAngle += Math.PI * 2;
// 1. Deform Flexspline
// Generates an ellipse pulled OUTWARDS towards the active magnetic poles (waveAngle and waveAngle + PI)
// Squeezed INWARDS at perpendicular axes (waveAngle + PI/2 and waveAngle - PI/2)
let bodyPath = "";
let teethPath = "";
const points = 120;
for (let i = 0; i <= points; i++) {
const theta = (i / points) * Math.PI * 2;
// Radial distance equation for elliptical deformation
// cos(2 * (theta - waveAngle)): Max (+1) at waveAngle, Min (-1) at waveAngle + PI/2
const r = R_FLEX_BASE + DEFORMATION_AMP * Math.cos(2 * (theta - waveAngle));
const bx = Math.cos(theta) * r;
const by = Math.sin(theta) * r;
// Teeth track slightly inside
const tx = Math.cos(theta) * (r - 6);
const ty = Math.sin(theta) * (r - 6);
if (i === 0) {
bodyPath += `M ${bx} ${by} `;
teethPath += `M ${tx} ${ty} `;
} else {
bodyPath += `L ${bx} ${by} `;
teethPath += `L ${tx} ${ty} `;
}
}
flexBody.setAttribute("d", bodyPath);
flexTeeth.setAttribute("d", teethPath);
// 2. Update Stator Magnets & Flux Lines
for (let i = 0; i < STATOR_COUNT; i++) {
const statorAngle = (i / STATOR_COUNT) * Math.PI * 2;
// Calculate intensity based on alignment with the rotating wave field
// Use power to sharpen the magnetic pole area
let intensity = Math.pow(Math.cos(statorAngle - waveAngle), 6);
const statorEl = document.getElementById(`stator-${i}`);
const fluxEl = document.getElementById(`flux-${i}`);
if (intensity > 0.1) {
statorEl.setAttribute("fill", "var(--accent-cyan)");
statorEl.setAttribute("filter", "url(#glow-cyan)");
// Draw flux line pulling the flexspline
const rFlexCurrent = R_FLEX_BASE + DEFORMATION_AMP * Math.cos(2 * (statorAngle - waveAngle));
const d = `M ${Math.cos(statorAngle)*R_STATOR_INNER} ${Math.sin(statorAngle)*R_STATOR_INNER}
L ${Math.cos(statorAngle)*(rFlexCurrent+5)} ${Math.sin(statorAngle)*(rFlexCurrent+5)}`;
fluxEl.setAttribute("d", d);
fluxEl.style.opacity = intensity;
// Animate dashes
fluxEl.setAttribute("stroke-dashoffset", -(Date.now() / 20) % 8);
} else {
statorEl.setAttribute("fill", "var(--bg-grid)");
statorEl.removeAttribute("filter");
fluxEl.style.opacity = 0;
}
}
// 3. Rotate Sun Gear
sunGearGroup.setAttribute("transform", `rotate(${(sunAngle * 180 / Math.PI)})`);
// 4. Update Mesh Highlights (Minor axis of ellipse)
const minorAxisAngle1 = waveAngle + Math.PI / 2;
const minorAxisAngle2 = waveAngle - Math.PI / 2;
// Function to generate short arc path for mesh highlight
const getArc = (angle, r) => {
const a1 = angle - 0.15;
const a2 = angle + 0.15;
return `M ${Math.cos(a1)*r} ${Math.sin(a1)*r} A ${r} ${r} 0 0 1 ${Math.cos(a2)*r} ${Math.sin(a2)*r}`;
};
meshTop.setAttribute("d", getArc(minorAxisAngle1, R_SUN + 2));
meshBot.setAttribute("d", getArc(minorAxisAngle2, R_SUN + 2));
// Show highlight only when moving, intensity based on speed
const isMoving = Math.abs(waveSpeed) > 0.001;
meshTop.style.opacity = isMoving ? 0.8 + 0.2*Math.sin(Date.now()/50) : 0;
meshBot.style.opacity = isMoving ? 0.8 + 0.2*Math.sin(Date.now()/50) : 0;
// 5. Update HUD Data
const rpmWave = (waveSpeed * 60 * 60 / (Math.PI * 2)).toFixed(0);
const rpmSun = (waveSpeed * GEAR_RATIO * 60 * 60 / (Math.PI * 2)).toFixed(1);
document.getElementById('val-wave-rpm').textContent = rpmWave + ' RPM';
document.getElementById('val-sun-rpm').textContent = rpmSun + ' RPM';
requestAnimationFrame(animate);
}
// Interactivity
slider.addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
waveSpeed = val * 0.02; // Map slider -3~3 to actual radian speed
document.getElementById('val-freq').textContent = val.toFixed(1) + ' Hz';
// Visual feedback for negative/positive speed
if(val < 0) {
document.getElementById('val-wave-rpm').style.color = "var(--accent-rose)";
} else {
document.getElementById('val-wave-rpm').style.color = "var(--accent-cyan)";
}
});
// Boot
window.addEventListener('DOMContentLoaded', () => {
initGeometry();
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
