<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>并行分流式叠加减速箱 · 原理动画</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@300;400;600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<style>
:root {
--bg: #060a14;
--surface: #0c1628;
--border: #1a3050;
--hs: #ff5722;
--hs-glow: rgba(255,87,34,0.35);
--ls: #00e5a0;
--ls-glow: rgba(0,229,160,0.30);
--shaft: #b0bec5;
--sleeve: #607d8b;
--amber: #ffc107;
--text: #cfd8dc;
--text-dim: #607d8b;
--panel: #0a1220;
}
*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }
html, body { width:100%; height:100%; overflow:hidden; background:var(--bg); font-family:'Rajdhani',sans-serif; color:var(--text); }
#app { display:flex; flex-direction:column; height:100vh; width:100vw; }
#svg-wrap { flex:1; display:flex; align-items:center; justify-content:center; min-height:0; padding:8px; }
#diagram { width:100%; height:100%; max-width:1400px; max-height:800px; }
#controls {
flex-shrink:0; display:flex; flex-wrap:wrap; gap:16px 28px;
padding:14px 24px 18px; background:var(--panel);
border-top:1px solid var(--border); align-items:center; justify-content:center;
}
.ctrl-group { display:flex; align-items:center; gap:8px; }
.ctrl-group label { font-size:13px; font-weight:600; letter-spacing:0.5px; white-space:nowrap; }
.ctrl-group .val { font-family:'Share Tech Mono',monospace; font-size:13px; min-width:52px; text-align:right; }
.hs-color { color:var(--hs); }
.ls-color { color:var(--ls); }
input[type=range] {
-webkit-appearance:none; width:140px; height:6px; border-radius:3px;
background:var(--border); outline:none; cursor:pointer;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance:none; width:16px; height:16px; border-radius:50%;
border:2px solid var(--bg); cursor:pointer;
}
#hs-rpm::-webkit-slider-thumb { background:var(--hs); }
#ls-rpm::-webkit-slider-thumb { background:var(--ls); }
.toggle-btn {
font-family:'Rajdhani',sans-serif; font-size:12px; font-weight:600;
padding:5px 14px; border:1px solid var(--border); border-radius:4px;
background:transparent; color:var(--text-dim); cursor:pointer;
letter-spacing:0.4px; transition:all .2s;
}
.toggle-btn.active { border-color:var(--amber); color:var(--amber); background:rgba(255,193,7,0.08); }
.toggle-btn:hover { border-color:var(--text); color:var(--text); }
#pause-btn { border-color:var(--text-dim); color:var(--text-dim); min-width:64px; }
#pause-btn.paused { border-color:#ef5350; color:#ef5350; }
@media (max-width:768px) {
#controls { gap:10px 16px; padding:10px 12px 14px; }
input[type=range] { width:100px; }
}
</style>
</head>
<body>
<div id="app">
<div id="svg-wrap">
<svg id="diagram" viewBox="0 0 1200 860" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 网格图案 -->
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M40,0 L0,0 0,40" fill="none" stroke="#0e1a2a" stroke-width="0.5"/>
</pattern>
<!-- HS发光 -->
<filter id="glow-hs" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- LS发光 -->
<filter id="glow-ls" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- 通用发光 -->
<filter id="glow-amber" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="6" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<!-- 箭头标记 HS -->
<marker id="arrow-hs" viewBox="0 0 10 6" refX="10" refY="3" markerWidth="8" markerHeight="6" orient="auto">
<path d="M0,0 L10,3 L0,6 Z" fill="var(--hs)"/>
</marker>
<!-- 箭头标记 LS -->
<marker id="arrow-ls" viewBox="0 0 10 6" refX="10" refY="3" markerWidth="8" markerHeight="6" orient="auto">
<path d="M0,0 L10,3 L0,6 Z" fill="var(--ls)"/>
</marker>
<!-- 渐变:箱体 -->
<linearGradient id="housing-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#132040"/>
<stop offset="100%" stop-color="#0a1428"/>
</linearGradient>
<!-- 渐变:釜体 -->
<linearGradient id="vessel-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#0c1628"/>
<stop offset="100%" stop-color="#070c18"/>
</linearGradient>
<!-- 剖面线图案 -->
<pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
<line x1="0" y1="0" x2="0" y2="6" stroke="#1a3050" stroke-width="0.8"/>
</pattern>
</defs>
<!-- 背景 -->
<rect width="1200" height="860" fill="var(--bg)"/>
<rect width="1200" height="860" fill="url(#grid)" opacity="0.6"/>
<!-- 标题 -->
<text x="600" y="36" text-anchor="middle" fill="#ffffff" font-family="Orbitron,sans-serif" font-size="20" font-weight="700" letter-spacing="3">PARALLEL SPLIT-FLOW GEARBOX</text>
<text x="600" y="58" text-anchor="middle" fill="var(--text-dim)" font-family="Rajdhani,sans-serif" font-size="14" font-weight="400" letter-spacing="1">并行分流式叠加减速箱 · 最终理想解原理动画</text>
<!-- ===== 釜体轮廓 ===== -->
<path d="M440,640 L440,820 Q440,850 470,850 L730,850 Q760,850 760,820 L760,640" fill="url(#vessel-grad)" stroke="#1a3050" stroke-width="1.5"/>
<!-- 釜内物料液面 -->
<path d="M445,720 Q520,710 600,715 Q680,720 755,712" fill="none" stroke="rgba(0,229,160,0.15)" stroke-width="1"/>
<path d="M445,740 Q530,732 600,736 Q670,740 755,734" fill="none" stroke="rgba(0,229,160,0.08)" stroke-width="1"/>
<!-- 釜盖法兰 -->
<rect x="410" y="628" width="380" height="16" rx="3" fill="#0f1c30" stroke="#1e3a5e" stroke-width="1.2"/>
<text x="400" y="640" text-anchor="end" fill="var(--text-dim)" font-family="Rajdhani,sans-serif" font-size="10">釜盖法兰</text>
<!-- 法兰螺栓 -->
<circle cx="425" cy="636" r="4" fill="#0a1220" stroke="#2a4a6a" stroke-width="0.8"/>
<circle cx="465" cy="636" r="4" fill="#0a1220" stroke="#2a4a6a" stroke-width="0.8"/>
<circle cx="735" cy="636" r="4" fill="#0a1220" stroke="#2a4a6a" stroke-width="0.8"/>
<circle cx="775" cy="636" r="4" fill="#0a1220" stroke="#2a4a6a" stroke-width="0.8"/>
<!-- ===== 减速箱箱体 ===== -->
<rect x="230" y="248" width="740" height="170" rx="8" fill="url(#housing-grad)" stroke="#1e3a5e" stroke-width="1.8"/>
<!-- 剖面线(箱体壁) -->
<rect x="230" y="248" width="740" height="170" rx="8" fill="url(#hatch)" opacity="0.25"/>
<!-- 箱体标注 -->
<text x="230" y="242" fill="var(--amber)" font-family="Rajdhani,sans-serif" font-size="11" font-weight="600">扁平共用箱体</text>
<!-- 高度标注线 -->
<line x1="210" y1="252" x2="210" y2="414" stroke="var(--amber)" stroke-width="0.8" stroke-dasharray="3,3"/>
<line x1="205" y1="252" x2="215" y2="252" stroke="var(--amber)" stroke-width="0.8"/>
<line x1="205" y1="414" x2="215" y2="414" stroke="var(--amber)" stroke-width="0.8"/>
<text x="207" y="340" text-anchor="middle" fill="var(--amber)" font-family="Share Tech Mono,monospace" font-size="10" transform="rotate(-90,207,340)">紧凑轴向高度</text>
<!-- ===== 高速电机 (HS) ===== -->
<g id="hs-motor-group">
<rect x="62" y="286" width="148" height="76" rx="6" fill="#1a0d05" stroke="var(--hs)" stroke-width="1.5" opacity="0.9"/>
<!-- 散热片纹理 -->
<line x1="75" y1="294" x2="75" y2="354" stroke="rgba(255,87,34,0.15)" stroke-width="1"/>
<line x1="88" y1="294" x2="88" y2="354" stroke="rgba(255,87,34,0.15)" stroke-width="1"/>
<line x1="101" y1="294" x2="101" y2="354" stroke="rgba(255,87,34,0.15)" stroke-width="1"/>
<line x1="114" y1="294" x2="114" y2="354" stroke="rgba(255,87,34,0.15)" stroke-width="1"/>
<text x="136" y="320" text-anchor="middle" fill="var(--hs)" font-family="Rajdhani,sans-serif" font-size="12" font-weight="700">高速电机</text>
<text x="136" y="336" text-anchor="middle" fill="rgba(255,87,34,0.6)" font-family="Share Tech Mono,monospace" font-size="9">HS MOTOR</text>
<!-- 转速指示 -->
<text id="hs-rpm-label" x="136" y="352" text-anchor="middle" fill="var(--hs)" font-family="Share Tech Mono,monospace" font-size="10">1200 RPM</text>
</g>
<!-- HS 水平输入轴 -->
<rect x="210" y="318" width="60" height="12" rx="2" fill="#2a1a10" stroke="var(--hs)" stroke-width="1"/>
<line x1="270" y1="324" x2="320" y2="324" stroke="var(--hs)" stroke-width="2" stroke-dasharray="0" filter="url(#glow-hs)" opacity="0.7"/>
<!-- ===== 低速电机 (LS) ===== -->
<g id="ls-motor-group">
<rect x="990" y="286" width="148" height="76" rx="6" fill="#051a12" stroke="var(--ls)" stroke-width="1.5" opacity="0.9"/>
<line x1="1003" y1="294" x2="1003" y2="354" stroke="rgba(0,229,160,0.15)" stroke-width="1"/>
<line x1="1016" y1="294" x2="1016" y2="354" stroke="rgba(0,229,160,0.15)" stroke-width="1"/>
<line x1="1029" y1="294" x2="1029" y2="354" stroke="rgba(0,229,160,0.15)" stroke-width="1"/>
<line x1="1042" y1="294" x2="1042" y2="354" stroke="rgba(0,229,160,0.15)" stroke-width="1"/>
<text x="1064" y="320" text-anchor="middle" fill="var(--ls)" font-family="Rajdhani,sans-serif" font-size="12" font-weight="700">低速电机</text>
<text x="1064" y="336" text-anchor="middle" fill="rgba(0,229,160,0.6)" font-family="Share Tech Mono,monospace" font-size="9">LS MOTOR</text>
<text id="ls-rpm-label" x="1064" y="352" text-anchor="middle" fill="var(--ls)" font-family="Share Tech Mono,monospace" font-size="10">200 RPM</text>
</g>
<!-- LS 水平输入轴 -->
<rect x="930" y="318" width="60" height="12" rx="2" fill="#0a2a1a" stroke="var(--ls)" stroke-width="1"/>
<line x1="880" y1="324" x2="930" y2="324" stroke="var(--ls)" stroke-width="2" filter="url(#glow-ls)" opacity="0.7"/>
<!-- ===== 内部齿轮机构 ===== -->
<!-- HS 伞齿轮对 -->
<g id="hs-bevel-pair">
<!-- 水平伞齿轮(小) -->
<g id="hs-bevel-h" transform="rotate(0,320,324)">
</g>
<!-- 垂直伞齿轮(大) -->
<g id="hs-bevel-v" transform="rotate(0,320,370)">
</g>
</g>
<!-- LS 伞齿轮对 -->
<g id="ls-bevel-pair">
<g id="ls-bevel-h" transform="rotate(0,880,324)">
</g>
<g id="ls-bevel-v" transform="rotate(0,880,370)">
</g>
</g>
<!-- 中心行星齿轮组 -->
<g id="planetary-group">
</g>
<!-- HS 传动轴(伞齿轮→中心) -->
<line x1="320" y1="380" x2="320" y2="400" stroke="var(--hs)" stroke-width="2" opacity="0.5"/>
<line x1="320" y1="400" x2="560" y2="400" stroke="var(--hs)" stroke-width="2" opacity="0.5" stroke-dasharray="6,3"/>
<line x1="560" y1="400" x2="560" y2="380" stroke="var(--hs)" stroke-width="2" opacity="0.5"/>
<!-- LS 传动轴(伞齿轮→中心) -->
<line x1="880" y1="380" x2="880" y2="400" stroke="var(--ls)" stroke-width="2" opacity="0.5"/>
<line x1="880" y1="400" x2="640" y2="400" stroke="var(--ls)" stroke-width="2" opacity="0.5" stroke-dasharray="6,3"/>
<line x1="640" y1="400" x2="640" y2="380" stroke="var(--ls)" stroke-width="2" opacity="0.5"/>
<!-- ===== 同轴输出轴 ===== -->
<!-- 60mm 空心轴套 -->
<rect id="sleeve-60" x="578" y="418" width="44" height="210" rx="3" fill="rgba(96,125,139,0.25)" stroke="var(--sleeve)" stroke-width="1.5"/>
<!-- 轴套旋转标记 -->
<g id="sleeve-marks">
<line x1="578" y1="470" x2="582" y2="470" stroke="var(--ls)" stroke-width="1.5" opacity="0.7"/>
<line x1="578" y1="530" x2="582" y2="530" stroke="var(--ls)" stroke-width="1.5" opacity="0.7"/>
<line x1="618" y1="500" x2="622" y2="500" stroke="var(--ls)" stroke-width="1.5" opacity="0.7"/>
<line x1="618" y1="560" x2="622" y2="560" stroke="var(--ls)" stroke-width="1.5" opacity="0.7"/>
</g>
<!-- 35mm 实心轴 -->
<rect id="shaft-35" x="589" y="418" width="22" height="222" rx="2" fill="rgba(176,190,197,0.2)" stroke="var(--shaft)" stroke-width="1.2"/>
<!-- 实心轴旋转标记 -->
<g id="shaft-marks">
<line x1="589" y1="460" x2="593" y2="460" stroke="var(--hs)" stroke-width="1.5" opacity="0.8"/>
<line x1="607" y1="490" x2="611" y2="490" stroke="var(--hs)" stroke-width="1.5" opacity="0.8"/>
<line x1="589" y1="540" x2="593" y2="540" stroke="var(--hs)" stroke-width="1.5" opacity="0.8"/>
<line x1="607" y1="580" x2="611" y2="580" stroke="var(--hs)" stroke-width="1.5" opacity="0.8"/>
</g>
<!-- 径向游隙标注 -->
<g id="clearance-group" visibility="hidden">
<rect x="585" y="495" width="30" height="30" rx="2" fill="none" stroke="var(--amber)" stroke-width="1.5" stroke-dasharray="3,2" filter="url(#glow-amber)"/>
<line x1="615" y1="510" x2="660" y2="480" stroke="var(--amber)" stroke-width="0.8"/>
<rect x="660" y="465" width="120" height="36" rx="4" fill="rgba(255,193,7,0.08)" stroke="var(--amber)" stroke-width="0.8"/>
<text x="720" y="479" text-anchor="middle" fill="var(--amber)" font-family="Rajdhani,sans-serif" font-size="10" font-weight="600">径向游隙 0.15mm</text>
<text x="720" y="494" text-anchor="middle" fill="rgba(255,193,7,0.7)" font-family="Share Tech Mono,monospace" font-size="9">Ø60 sleeve / Ø35 shaft</text>
<!-- 放大视图 -->
<rect x="660" y="508" width="100" height="50" rx="3" fill="#0a1020" stroke="var(--amber)" stroke-width="0.6"/>
<text x="710" y="520" text-anchor="middle" fill="rgba(255,193,7,0.5)" font-family="Share Tech Mono,monospace" font-size="7">ZOOM ×50</text>
<!-- 放大后的轴套截面 -->
<circle cx="710" cy="538" r="14" fill="none" stroke="var(--sleeve)" stroke-width="1.5"/>
<circle cx="710" cy="538" r="9" fill="none" stroke="var(--shaft)" stroke-width="1.2"/>
<!-- 游隙高亮 -->
<circle cx="710" cy="538" r="11" fill="none" stroke="var(--amber)" stroke-width="0.6" stroke-dasharray="2,2" opacity="0.8"/>
</g>
<!-- ===== 输出工具 ===== -->
<!-- 刮壁框(连接60mm轴套) -->
<g id="scraper-group">
<rect x="490" y="625" width="8" height="60" rx="2" fill="rgba(0,229,160,0.15)" stroke="var(--ls)" stroke-width="1"/>
<rect x="702" y="625" width="8" height="60" rx="2" fill="rgba(0,229,160,0.15)" stroke="var(--ls)" stroke-width="1"/>
<rect x="490" y="621" width="220" height="8" rx="2" fill="rgba(0,229,160,0.15)" stroke="var(--ls)" stroke-width="1"/>
<!-- 刮壁桨叶 -->
<rect x="486" y="680" width="16" height="4" rx="1" fill="var(--ls)" opacity="0.6"/>
<rect x="698" y="680" width="16" height="4" rx="1" fill="var(--ls)" opacity="0.6"/>
<text x="478" y="660" text-anchor="end" fill="var(--ls)" font-family="Rajdhani,sans-serif" font-size="9" opacity="0.7">刮壁框</text>
</g>
<!-- 分散盘(连接35mm轴) -->
<g id="disperser-group">
<rect x="560" y="635" width="80" height="8" rx="3" fill="rgba(255,87,34,0.2)" stroke="var(--hs)" stroke-width="1.2"/>
<!-- 分散盘齿 -->
<rect x="558" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<rect x="574" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<rect x="590" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<rect x="606" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<rect x="622" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<rect x="636" y="643" width="6" height="6" rx="1" fill="var(--hs)" opacity="0.5"/>
<text x="648" y="648" fill="var(--hs)" font-family="Rajdhani,sans-serif" font-size="9" opacity="0.7">分散盘</text>
</g>
<!-- ===== 动力流粒子容器 ===== -->
<g id="power-flow-hs"></g>
<g id="power-flow-ls"></g>
<!-- ===== 偏置距离标注 ===== -->
<line x1="320" y1="235" x2="600" y2="235" stroke="var(--text-dim)" stroke-width="0.8" marker-end="url(#arrow-hs)" opacity="0.5"/>
<line x1="880" y1="235" x2="600" y2="235" stroke="var(--text-dim)" stroke-width="0.8" marker-end="url(#arrow-ls)" opacity="0.5"/>
<line x1="320" y1="228" x2="320" y2="242" stroke="var(--text-dim)" stroke-width="0.8" opacity="0.5"/>
<line x1="880" y1="228" x2="880" y2="242" stroke="var(--text-dim)" stroke-width="0.8" opacity="0.5"/>
<text x="440" y="230" fill="var(--text-dim)" font-family="Share Tech Mono,monospace" font-size="9">偏置 120mm</text>
<text x="700" y="230" fill="var(--text-dim)" font-family="Share Tech Mono,monospace" font-size="9">偏置 120mm</text>
<!-- 轴径标注 -->
<text x="570" y="450" text-anchor="end" fill="var(--sleeve)" font-family="Share Tech Mono,monospace" font-size="8">Ø60 空心轴套</text>
<text x="570" y="462" text-anchor="end" fill="var(--shaft)" font-family="Share Tech Mono,monospace" font-size="8">Ø35 实心轴</text>
<!-- ===== IFR 理想解标注 ===== -->
<g id="ifr-badge">
<rect x="920" y="80" width="240" height="60" rx="6" fill="rgba(255,193,7,0.06)" stroke="var(--amber)" stroke-width="0.8"/>
<text x="940" y="100" fill="var(--amber)" font-family="Orbitron,sans-serif" font-size="10" font-weight="700">IFR · 最终理想解</text>
<text x="940" y="116" fill="var(--text-dim)" font-family="Rajdhani,sans-serif" font-size="10">轴向高度↓ 重心↓ 稳定性↑</text>
<text x="940" y="130" fill="var(--text-dim)" font-family="Rajdhani,sans-serif" font-size="10">双动力解耦 · 同轴汇合输出</text>
</g>
<!-- 旋转方向指示弧 -->
<g id="rotation-indicators">
<!-- HS 旋转箭头 -->
<path id="hs-rot-arc" d="" fill="none" stroke="var(--hs)" stroke-width="1.2" opacity="0.6"/>
<!-- LS 旋转箭头 -->
<path id="ls-rot-arc" d="" fill="none" stroke="var(--ls)" stroke-width="1.2" opacity="0.6"/>
</g>
</svg>
</div>
<div id="controls">
<div class="ctrl-group">
<label class="hs-color">高速电机</label>
<input type="range" id="hs-rpm" min="0" max="3000" value="1200" step="50">
<span class="val hs-color" id="hs-rpm-val">1200</span>
<span style="font-size:11px;color:var(--text-dim)">RPM</span>
</div>
<div class="ctrl-group">
<label class="ls-color">低速电机</label>
<input type="range" id="ls-rpm" min="0" max="500" value="200" step="10">
<span class="val ls-color" id="ls-rpm-val">200</span>
<span style="font-size:11px;color:var(--text-dim)">RPM</span>
</div>
<div class="ctrl-group">
<button class="toggle-btn active" id="flow-btn">动力流</button>
</div>
<div class="ctrl-group">
<button class="toggle-btn" id="clearance-btn">径向游隙</button>
</div>
<div class="ctrl-group">
<button class="toggle-btn" id="pause-btn">暂停</button>
</div>
</div>
</div>
<script>
(function() {
'use strict';
const NS = 'http://www.w3.org/2000/svg';
const svg = document.getElementById('diagram');
// === 配置 ===
const CFG = {
hsRPM: 1200,
lsRPM: 200,
showFlow: true,
showClearance: false,
paused: false
};
// === 动画状态 ===
let hsAngle = 0, lsAngle = 0;
let prevTime = 0;
let globalTime = 0;
// === 齿轮路径生成 ===
function gearPath(teeth, outerR, innerR) {
const pts = [];
const step = (Math.PI * 2) / teeth;
for (let i = 0; i < teeth; i++) {
const a = i * step;
pts.push([outerR * Math.cos(a - step * 0.18), outerR * Math.sin(a - step * 0.18)]);
pts.push([outerR * Math.cos(a + step * 0.18), outerR * Math.sin(a + step * 0.18)]);
pts.push([innerR * Math.cos(a + step * 0.32), innerR * Math.sin(a + step * 0.32)]);
pts.push([innerR * Math.cos(a + step * 0.68), innerR * Math.sin(a + step * 0.68)]);
}
return 'M' + pts.map(p => p[0].toFixed(1) + ',' + p[1].toFixed(1)).join('L') + 'Z';
}
// === 创建齿轮SVG元素 ===
function createGearElement(parentId, cx, cy, teeth, outerR, innerR, holeR, color, strokeColor) {
const parent = document.getElementById(parentId);
const g = document.createElementNS(NS, 'g');
const path = document.createElementNS(NS, 'path');
path.setAttribute('d', gearPath(teeth, outerR, innerR));
path.setAttribute('fill', color);
path.setAttribute('stroke', strokeColor || 'rgba(255,255,255,0.2)');
path.setAttribute('stroke-width', '0.6');
path.setAttribute('transform', `translate(${cx},${cy})`);
g.appendChild(path);
// 中心孔
if (holeR > 0) {
const hole = document.createElementNS(NS, 'circle');
hole.setAttribute('cx', cx);
hole.setAttribute('cy', cy);
hole.setAttribute('r', holeR);
hole.setAttribute('fill', '#0a1020');
hole.setAttribute('stroke', strokeColor || 'rgba(255,255,255,0.15)');
hole.setAttribute('stroke-width', '0.5');
g.appendChild(hole);
}
parent.appendChild(g);
return { group: g, cx, cy, teeth, path };
}
// === 创建伞齿轮截面 ===
function createBevelGearSection(parentId, cx, cy, isHorizontal, color, size) {
const parent = document.getElementById(parentId);
const g = document.createElementNS(NS, 'g');
if (isHorizontal) {
// 水平伞齿轮截面 — 梯形
const w1 = size * 1.2, w2 = size * 0.6, h = size * 0.9;
const d = `M${cx - w1/2},${cy - h/2} L${cx + w1/2},${cy - h/2} L${cx + w2/2},${cy + h/2} L${cx - w2/2},${cy + h/2} Z`;
const path = document.createElementNS(NS, 'path');
path.setAttribute('d', d);
path.setAttribute('fill', color);
path.setAttribute('stroke', 'rgba(255,255,255,0.25)');
path.setAttribute('stroke-width', '0.8');
g.appendChild(path);
// 齿纹理线
for (let i = 0; i < 4; i++) {
const t = (i + 1) / 5;
const lw = w1 + (w2 - w1) * t;
const ly = cy - h/2 + h * t;
const line = document.createElementNS(NS, 'line');
line.setAttribute('x1', cx - lw/2);
line.setAttribute('y1', ly);
line.setAttribute('x2', cx + lw/2);
line.setAttribute('y2', ly);
line.setAttribute('stroke', 'rgba(255,255,255,0.12)');
line.setAttribute('stroke-width', '0.5');
g.appendChild(line);
}
} else {
// 垂直伞齿轮截面 — 梯形(竖向)
const h1 = size * 1.2, h2 = size * 0.6, w = size * 0.9;
const d = `M${cx - w/2},${cy - h1/2} L${cx + w/2},${cy - h1/2} L${cx + w/2},${cy + h2/2} L${cx - w/2},${cy + h2/2} Z`;
const path = document.createElementNS(NS, 'path');
path.setAttribute('d', d);
path.setAttribute('fill', color);
path.setAttribute('stroke', 'rgba(255,255,255,0.25)');
path.setAttribute('stroke-width', '0.8');
g.appendChild(path);
for (let i = 0; i < 4; i++) {
const t = (i + 1) / 5;
const lh = h1 + (h2 - h1) * t;
const ly = cy - h1/2 + (h1/2 + h2/2) * t;
const line = document.createElementNS(NS, 'line');
line.setAttribute('x1', cx - w/2);
line.setAttribute('y1', ly);
line.setAttribute('x2', cx + w/2);
line.setAttribute('y2', ly);
line.setAttribute('stroke', 'rgba(255,255,255,0.12)');
line.setAttribute('stroke-width', '0.5');
g.appendChild(line);
}
}
parent.appendChild(g);
return { group: g, cx, cy };
}
// === 创建行星齿轮组 ===
function createPlanetaryGroup() {
const parent = document.getElementById('planetary-group');
const cx = 600, cy = 365;
// 外齿圈(连接低速 → 60mm轴套)
const ring = document.createElementNS(NS, 'circle');
ring.setAttribute('cx', cx);
ring.setAttribute('cy', cy);
ring.setAttribute('r', 42);
ring.setAttribute('fill', 'none');
ring.setAttribute('stroke', 'var(--ls)');
ring.setAttribute('stroke-width', '3');
ring.setAttribute('stroke-dasharray', '4,2');
ring.setAttribute('opacity', '0.6');
parent.appendChild(ring);
// 齿圈内齿纹理
const ringTeeth = document.createElementNS(NS, 'circle');
ringTeeth.setAttribute('cx', cx);
ringTeeth.setAttribute('cy', cy);
ringTeeth.setAttribute('r', 39);
ringTeeth.setAttribute('fill', 'none');
ringTeeth.setAttribute('stroke', 'var(--ls)');
ringTeeth.setAttribute('stroke-width', '0.5');
ringTeeth.setAttribute('stroke-dasharray', '2,3');
ringTeeth.setAttribute('opacity', '0.4');
parent.appendChild(ringTeeth);
// 行星齿轮(3个)
const planetPositions = [
{ x: cx + 26, y: cy - 15 },
{ x: cx - 22, y: cy - 10 },
{ x: cx, y: cy + 26 }
];
const planetGears = [];
planetPositions.forEach(pos => {
const pg = document.createElementNS(NS, 'g');
const p = document.createElementNS(NS, 'path');
p.setAttribute('d', gearPath(8, 11, 8));
p.setAttribute('transform', `translate(${pos.x},${pos.y})`);
p.setAttribute('fill', 'rgba(176,190,197,0.2)');
p.setAttribute('stroke', 'rgba(176,190,197,0.4)');
p.setAttribute('stroke-width', '0.5');
pg.appendChild(p);
const hole = document.createElementNS(NS, 'circle');
hole.setAttribute('cx', pos.x);
hole.setAttribute('cy', pos.y);
hole.setAttribute('r', 3);
hole.setAttribute('fill', '#0a1020');
hole.setAttribute('stroke', 'rgba(176,190,197,0.3)');
hole.setAttribute('stroke-width', '0.4');
pg.appendChild(hole);
parent.appendChild(pg);
planetGears.push({ group: pg, path: p, ...pos });
});
// 太阳轮(连接高速 → 35mm轴)
const sunGear = createGearElement('planetary-group', cx, cy, 10, 16, 12, 4, 'rgba(255,87,34,0.25)', 'var(--hs)');
// 标注
const sunLabel = document.createElementNS(NS, 'text');
sunLabel.setAttribute('x', cx);
sunLabel.setAttribute('y', cy + 55);
sunLabel.setAttribute('text-anchor', 'middle');
sunLabel.setAttribute('fill', 'var(--text-dim)');
sunLabel.setAttribute('font-family', 'Rajdhani,sans-serif');
sunLabel.setAttribute('font-size', '9');
sunLabel.textContent = '行星齿轮同轴汇合';
parent.appendChild(sunLabel);
return { planetGears, sunGear, cx, cy };
}
// === 动力流粒子系统 ===
const hsParticles = [];
const lsParticles = [];
// HS动力流路径关键点
const hsPath = [
{ x: 210, y: 324 }, // 电机输出
{ x: 320, y: 324 }, // 伞齿轮
{ x: 320, y: 370 }, // 伞齿轮换向
{ x: 320, y: 400 }, // 传动轴
{ x: 560, y: 400 }, // 传动至中心
{ x: 600, y: 370 }, // 太阳轮
{ x: 600, y: 418 }, // 输出轴起点
{ x: 600, y: 640 } // 分散盘
];
// LS动力流路径关键点
const lsPath = [
{ x: 990, y: 324 }, // 电机输出
{ x: 880, y: 324 }, // 伞齿轮
{ x: 880, y: 370 }, // 伞齿轮换向
{ x: 880, y: 400 }, // 传动轴
{ x: 640, y: 400 }, // 传动至中心
{ x: 600, y: 365 }, // 齿圈
{ x: 600, y: 418 }, // 输出轴套起点
{ x: 600, y: 625 } // 刮壁框
];
// 沿路径插值
function interpolatePath(pathPoints, t) {
t = ((t % 1) + 1) % 1;
const totalSegments = pathPoints.length - 1;
const segFloat = t * totalSegments;
const segIndex = Math.min(Math.floor(segFloat), totalSegments - 1);
const segT = segFloat - segIndex;
const p1 = pathPoints[segIndex];
const p2 = pathPoints[segIndex + 1];
return {
x: p1.x + (p2.x - p1.x) * segT,
y: p1.y + (p2.y - p1.y) * segT
};
}
// 创建粒子
function createParticles(container, pathPoints, color, count) {
const particles = [];
const parentEl = document.getElementById(container);
for (let i = 0; i < count; i++) {
const circle = document.createElementNS(NS, 'circle');
circle.setAttribute('r', '2.5');
circle.setAttribute('fill', color);
circle.setAttribute('opacity', '0');
parentEl.appendChild(circle);
particles.push({
el: circle,
t: i / count,
speed: 0.12 + Math.random() * 0.03
});
}
return particles;
}
// === 伞齿轮对 ===
let hsBevelH, hsBevelV, lsBevelH, lsBevelV;
let planetaryData;
// === 初始化 ===
function init() {
// HS 伞齿轮
hsBevelH = createBevelGearSection('hs-bevel-h', 0, 0, true, 'rgba(255,87,34,0.3)', 30);
hsBevelV = createBevelGearSection('hs-bevel-v', 0, 0, false, 'rgba(255,87,34,0.25)', 26);
// LS 伞齿轮
lsBevelH = createBevelGearSection('ls-bevel-h', 0, 0, true, 'rgba(0,229,160,0.3)', 30);
lsBevelV = createBevelGearSection('ls-bevel-v', 0, 0, false, 'rgba(0,229,160,0.25)', 26);
// 行星齿轮组
planetaryData = createPlanetaryGroup();
// 创建动力流粒子
const hsP = createParticles('power-flow-hs', hsPath, 'var(--hs)', 14);
hsParticles.push(...hsP);
const lsP = createParticles('power-flow-ls', lsPath, 'var(--ls)', 14);
lsParticles.push(...lsP);
// 设置控件
setupControls();
// 开始动画
requestAnimationFrame(animate);
}
// === 控件设置 ===
function setupControls() {
const hsSlider = document.getElementById('hs-rpm');
const lsSlider = document.getElementById('ls-rpm');
const hsVal = document.getElementById('hs-rpm-val');
const lsVal = document.getElementById('ls-rpm-val');
const hsLabel = document.getElementById('hs-rpm-label');
const lsLabel = document.getElementById('ls-rpm-label');
const flowBtn = document.getElementById('flow-btn');
const clearanceBtn = document.getElementById('clearance-btn');
const pauseBtn = document.getElementById('pause-btn');
hsSlider.addEventListener('input', () => {
CFG.hsRPM = parseInt(hsSlider.value);
hsVal.textContent = CFG.hsRPM;
hsLabel.textContent = CFG.hsRPM + ' RPM';
});
lsSlider.addEventListener('input', () => {
CFG.lsRPM = parseInt(lsSlider.value);
lsVal.textContent = CFG.lsRPM;
lsLabel.textContent = CFG.lsRPM + ' RPM';
});
flowBtn.addEventListener('click', () => {
CFG.showFlow = !CFG.showFlow;
flowBtn.classList.toggle('active', CFG.showFlow);
document.getElementById('power-flow-hs').style.display = CFG.showFlow ? '' : 'none';
document.getElementById('power-flow-ls').style.display = CFG.showFlow ? '' : 'none';
});
clearanceBtn.addEventListener('click', () => {
CFG.showClearance = !CFG.showClearance;
clearanceBtn.classList.toggle('active', CFG.showClearance);
document.getElementById('clearance-group').setAttribute('visibility', CFG.showClearance ? 'visible' : 'hidden');
});
pauseBtn.addEventListener('click', () => {
CFG.paused = !CFG.paused;
pauseBtn.classList.toggle('paused', CFG.paused);
pauseBtn.textContent = CFG.paused ? '继续' : '暂停';
});
}
// === 更新旋转标记 ===
function updateShaftMarks(angle, isHS) {
const marks = document.getElementById(isHS ? 'shaft-marks' : 'sleeve-marks');
const lines = marks.querySelectorAll('line');
const cx = 600;
const r = isHS ? 11 : 22;
lines.forEach((line, i) => {
const baseY = isHS
? [460, 490, 540, 580][i]
: [470, 530, 500, 560][i];
const dir = (i % 2 === 0) ? -1 : 1;
const a = angle * (isHS ? 1 : -0.5) + i * 1.2;
const xOff = Math.sin(a) * r;
line.setAttribute('x1', cx + xOff - (isHS ? 11 : 22));
line.setAttribute('x2', cx + xOff - (isHS ? 11 : 22) + 4);
});
}
// === 更新旋转弧线指示器 ===
function updateRotationArcs() {
const hsArc = document.getElementById('hs-rot-arc');
const lsArc = document.getElementById('ls-rot-arc');
// 分散盘旋转弧
const hsCx = 600, hsCy = 639, hsR = 52;
const hsStartAngle = hsAngle * 0.3;
const hsEndAngle = hsStartAngle + Math.PI * 0.8;
const x1 = hsCx + hsR * Math.cos(hsStartAngle);
const y1 = hsCy + hsR * Math.sin(hsStartAngle);
const x2 = hsCx + hsR * Math.cos(hsEndAngle);
const y2 = hsCy + hsR * Math.sin(hsEndAngle);
hsArc.setAttribute('d', `M${x1.toFixed(1)},${y1.toFixed(1)} A${hsR},${hsR} 0 0,1 ${x2.toFixed(1)},${y2.toFixed(1)}`);
// 刮壁框旋转弧
const lsCx = 600, lsCy = 625, lsR = 80;
const lsStartAngle = -lsAngle * 0.15;
const lsEndAngle = lsStartAngle + Math.PI * 0.6;
const lx1 = lsCx + lsR * Math.cos(lsStartAngle);
const ly1 = lsCy + lsR * Math.sin(lsStartAngle);
const lx2 = lsCx + lsR * Math.cos(lsEndAngle);
const ly2 = lsCy + lsR * Math.sin(lsEndAngle);
lsArc.setAttribute('d', `M${lx1.toFixed(1)},${ly1.toFixed(1)} A${lsR},${lsR} 0 0,0 ${lx2.toFixed(1)},${ly2.toFixed(1)}`);
}
// === 动画主循环 ===
function animate(timestamp) {
if (prevTime === 0) prevTime = timestamp;
const dt = Math.min((timestamp - prevTime) / 1000, 0.1);
prevTime = timestamp;
if (!CFG.paused) {
globalTime += dt;
// 更新齿轮角度(按RPM比例缩放,视觉上降速以便观察)
const visualScale = 0.003;
hsAngle += (CFG.hsRPM / 60) * dt * Math.PI * 2 * visualScale;
lsAngle += (CFG.lsRPM / 60) * dt * Math.PI * 2 * visualScale;
// 更新伞齿轮旋转
const hsBevelHGroup = document.getElementById('hs-bevel-h');
const hsBevelVGroup = document.getElementById('hs-bevel-v');
const lsBevelHGroup = document.getElementById('ls-bevel-h');
const lsBevelVGroup = document.getElementById('ls-bevel-v');
hsBevelHGroup.setAttribute('transform', `rotate(${(hsAngle * 180 / Math.PI).toFixed(1)},320,324)`);
hsBevelVGroup.setAttribute('transform', `rotate(${(hsAngle * 180 / Math.PI * 0.6).toFixed(1)},320,370)`);
lsBevelHGroup.setAttribute('transform', `rotate(${(lsAngle * 180 / Math.PI).toFixed(1)},880,324)`);
lsBevelVGroup.setAttribute('transform', `rotate(${(lsAngle * 180 / Math.PI * 0.6).toFixed(1)},880,370)`);
// 更新太阳轮旋转
if (planetaryData && planetaryData.sunGear) {
const sunPath = planetaryData.sunGear.path;
const sunAngle = (hsAngle * 180 / Math.PI).toFixed(1);
sunPath.setAttribute('transform', `translate(${planetaryData.sunGear.cx},${planetaryData.sunGear.cy}) rotate(${sunAngle})`);
}
// 更新行星齿轮自转
if (planetaryData && planetaryData.planetGears) {
planetaryData.planetGears.forEach((pg, i) => {
const pAngle = (-hsAngle * 0.6 * 180 / Math.PI + i * 120).toFixed(1);
pg.path.setAttribute('transform', `translate(${pg.x},${pg.y}) rotate(${pAngle})`);
});
}
// 更新输出工具旋转
const scraperGroup = document.getElementById('scraper-group');
const disperserGroup = document.getElementById('disperser-group');
const lsRotDeg = (lsAngle * 180 / Math.PI * -0.5).toFixed(1);
const hsRotDeg = (hsAngle * 180 / Math.PI).toFixed(1);
scraperGroup.setAttribute('transform', `rotate(${lsRotDeg},600,625)`);
disperserGroup.setAttribute('transform', `rotate(${hsRotDeg},600,639)`);
// 更新旋转弧线
updateRotationArcs();
// 更新动力流粒子
if (CFG.showFlow) {
const hsSpeed = Math.max(CFG.hsRPM / 1200, 0.1);
const lsSpeed = Math.max(CFG.lsRPM / 200, 0.1);
hsParticles.forEach(p => {
p.t += p.speed * hsSpeed * dt;
if (p.t > 1) p.t -= 1;
const pos = interpolatePath(hsPath, p.t);
p.el.setAttribute('cx', pos.x.toFixed(1));
p.el.setAttribute('cy', pos.y.toFixed(1));
// 在路径两端淡入淡出
const fade = Math.min(p.t * 5, (1 - p.t) * 5, 1);
p.el.setAttribute('opacity', (fade * 0.85).toFixed(2));
p.el.setAttribute('r', (2 + fade * 1.2).toFixed(1));
});
lsParticles.forEach(p => {
p.t += p.speed * lsSpeed * dt;
if (p.t > 1) p.t -= 1;
const pos = interpolatePath(lsPath, p.t);
p.el.setAttribute('cx', pos.x.toFixed(1));
p.el.setAttribute('cy', pos.y.toFixed(1));
const fade = Math.min(p.t * 5, (1 - p.t) * 5, 1);
p.el.setAttribute('opacity', (fade * 0.85).toFixed(2));
p.el.setAttribute('r', (2 + fade * 1.2).toFixed(1));
});
}
// 径向游隙闪烁效果
if (CFG.showClearance) {
const pulse = 0.5 + 0.5 * Math.sin(globalTime * 4);
const clearanceGroup = document.getElementById('clearance-group');
clearanceGroup.setAttribute('opacity', (0.6 + pulse * 0.4).toFixed(2));
}
}
requestAnimationFrame(animate);
}
// 启动
init();
})();
</script>
</body>
</html>
实现说明:
这是一个基于 SVG + 原生 JavaScript 的交互式原理动画,聚焦展示"并行分流式叠加减速箱"的最终理想解工作原理:
视觉架构:
- 深色工业蓝图风格背景,带微网格纹理营造工程制图氛围
- 高速通路(橙色
#ff5722)与低速通路(青绿色#00e5a0)双色编码,贯穿从电机输入到输出工具的完整路径 - 扁平箱体剖面采用渐变填充+剖面线纹理,强调"紧凑轴向高度"这一核心 IFR 特征
核心动画:
- 伞齿轮对旋转 — 左右两组伞齿轮分别按高速/低速比转动,展示 90° 空间换向
- 行星齿轮同轴汇合 — 中心太阳轮(橙色/高速→35mm轴)与外齿圈(青绿色/低速→60mm轴套)可视化分离传动
- 输出工具差速旋转 — 分散盘(高速)与刮壁框(低速)独立旋转,旋转弧线指示方向
- 动力流粒子 — 14 个粒子沿各自路径流动,速度随 RPM 滑块实时变化,两端自动淡入淡出
交互控件:
- 高速/低速 RPM 滑块 — 实时调节电机转速,齿轮旋转速度与粒子流速同步响应
- 动力流按钮 — 切换粒子流可见性
- 径向游隙按钮 — 激活后高亮 Ø60 轴套与 Ø35 实心轴之间的 0.15mm 游隙区域,含 50× 放大截面图与脉冲动画
- 暂停/继续 — 冻结/恢复全部动画
积分规则:第一轮对话扣减6分,后续每轮扣4分
等待动画代码生成...
