<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IFR原理动画 — 矩阵自定心滚轮·超高压水射流切割</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@300;500;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
<style>
:root {
--bg: #060a12;
--grid: #0d1420;
--steel: #6b7d96;
--steel-light: #94a7bf;
--cable: #c78c2e;
--cable-dark: #8a5f1a;
--water: #00e5ff;
--water-deep: #0077b6;
--measure: #ff8f00;
--lock-red: #ff1744;
--unlock-green: #00e676;
--ifr-line: #76ff03;
--panel-bg: #0b1120;
--text: #d0dae8;
--text-dim: #5a6e85;
--accent: #00e5ff;
}
* { margin:0; padding:0; box-sizing:border-box; }
body {
background: var(--bg);
color: var(--text);
font-family: 'Rajdhani', sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
overflow-x: hidden;
}
.wrapper {
width: 100%;
max-width: 1500px;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.title-bar {
display: flex;
align-items: baseline;
gap: 16px;
width: 100%;
padding: 0 8px;
}
.title-bar h1 {
font-size: 22px;
font-weight: 700;
letter-spacing: 1px;
color: var(--accent);
text-transform: uppercase;
}
.title-bar .subtitle {
font-size: 13px;
color: var(--text-dim);
font-family: 'Share Tech Mono', monospace;
}
.svg-container {
width: 100%;
border: 1px solid #1a2744;
border-radius: 8px;
overflow: hidden;
background: var(--bg);
box-shadow: 0 0 60px rgba(0,229,255,0.04), inset 0 0 80px rgba(0,0,0,0.4);
}
.svg-container svg {
display: block;
width: 100%;
height: auto;
}
.controls {
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: stretch;
}
.ctrl-group {
background: var(--panel-bg);
border: 1px solid #1a2744;
border-radius: 8px;
padding: 14px 18px;
flex: 1;
min-width: 220px;
}
.ctrl-group label {
display: block;
font-size: 11px;
text-transform: uppercase;
letter-spacing: 2px;
color: var(--text-dim);
margin-bottom: 8px;
font-family: 'Share Tech Mono', monospace;
}
.ctrl-group .value-display {
font-size: 28px;
font-weight: 700;
color: var(--accent);
line-height: 1;
margin-bottom: 6px;
}
.ctrl-group .value-display .unit {
font-size: 14px;
font-weight: 300;
color: var(--text-dim);
margin-left: 4px;
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
height: 6px;
border-radius: 3px;
background: #1a2744;
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px; height: 18px;
border-radius: 50%;
background: var(--accent);
cursor: pointer;
box-shadow: 0 0 8px rgba(0,229,255,0.5);
}
.btn-row {
display: flex;
gap: 8px;
margin-top: 10px;
}
.btn {
font-family: 'Share Tech Mono', monospace;
font-size: 12px;
padding: 6px 14px;
border: 1px solid #2a3a55;
border-radius: 4px;
background: #111b2e;
color: var(--text);
cursor: pointer;
transition: all .2s;
text-transform: uppercase;
letter-spacing: 1px;
}
.btn:hover { background: #1a2b48; border-color: var(--accent); color: #fff; }
.btn.active { background: #0a3a5a; border-color: var(--accent); color: var(--accent); }
.phase-indicator {
display: flex;
gap: 4px;
margin-top: 8px;
}
.phase-dot {
width: 10px; height: 10px;
border-radius: 50%;
background: #1a2744;
transition: background .3s, box-shadow .3s;
}
.phase-dot.active {
background: var(--accent);
box-shadow: 0 0 8px var(--accent);
}
.phase-dot.red { background: var(--lock-red); box-shadow: 0 0 8px var(--lock-red); }
.phase-dot.amber { background: var(--measure); box-shadow: 0 0 8px var(--measure); }
.phase-dot.cyan { background: var(--water); box-shadow: 0 0 8px var(--water); }
.phase-dot.green { background: var(--unlock-green); box-shadow: 0 0 8px var(--unlock-green); }
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}
</style>
</head>
<body>
<div class="wrapper">
<div class="title-bar">
<h1>IFR 原理动画</h1>
<span class="subtitle">矩阵自定心滚轮 · 超高压水射流切割 — 5140mm跨度电缆精密切断</span>
</div>
<div class="svg-container">
<svg id="mainSvg" viewBox="0 0 1400 820" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 工程网格 -->
<pattern id="gridSmall" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#0f1825" stroke-width="0.5"/>
</pattern>
<pattern id="gridLarge" width="100" height="100" patternUnits="userSpaceOnUse">
<rect width="100" height="100" fill="url(#gridSmall)"/>
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="#141f30" stroke-width="1"/>
</pattern>
<!-- 金属渐变 -->
<linearGradient id="steelGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#8fa4bd"/>
<stop offset="40%" stop-color="#5a7089"/>
<stop offset="100%" stop-color="#3a4f66"/>
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#a0b4cc"/>
<stop offset="50%" stop-color="#6b82a0"/>
<stop offset="100%" stop-color="#4a5f78"/>
</linearGradient>
<linearGradient id="cableGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#daa540"/>
<stop offset="30%" stop-color="#c78c2e"/>
<stop offset="70%" stop-color="#a06e1c"/>
<stop offset="100%" stop-color="#7a5214"/>
</linearGradient>
<linearGradient id="waterGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#00e5ff" stop-opacity="0.9"/>
<stop offset="50%" stop-color="#00b8d4" stop-opacity="0.7"/>
<stop offset="100%" stop-color="#0077b6" stop-opacity="0.3"/>
</linearGradient>
<linearGradient id="nozzleGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#556680"/>
<stop offset="100%" stop-color="#2a3a50"/>
</linearGradient>
<!-- 水射流发光 -->
<filter id="waterGlow" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" result="blur"/>
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
</filter>
<filter id="strongGlow" x="-100%" y="-100%" width="300%" height="300%">
<feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur"/>
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
</filter>
<filter id="softGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" result="blur"/>
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="ifrGlow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur"/>
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- 锥形滚轮标记 (用于截面图) -->
<clipPath id="crossClip">
<rect x="1085" y="55" width="300" height="295" rx="6"/>
</clipPath>
</defs>
<!-- 背景 -->
<rect width="1400" height="820" fill="url(#gridLarge)"/>
<!-- ===== 主体区域 ===== -->
<!-- 理想中心面 — IFR核心视觉 -->
<line id="ifrLine" x1="60" y1="430" x2="1070" y2="430"
stroke="#76ff03" stroke-width="1.2" stroke-dasharray="12,6" opacity="0.7" filter="url(#ifrGlow)"/>
<text x="65" y="422" fill="#76ff03" font-size="11" font-family="Share Tech Mono, monospace" opacity="0.9">
IFR 理想中心面 — 恒定不变
</text>
<!-- 中心面公差标注 -->
<line x1="60" y1="430" x2="60" y2="430" stroke="#76ff03" stroke-width="0.5" opacity="0.4"/>
<text id="toleranceLabel" x="65" y="446" fill="#76ff03" font-size="9" font-family="Share Tech Mono, monospace" opacity="0.6">
公差 ±0.2mm
</text>
<!-- 机架底座 -->
<rect x="80" y="540" width="980" height="12" rx="2" fill="#1a2744" stroke="#2a3a55" stroke-width="0.5"/>
<rect x="80" y="290" width="980" height="8" rx="2" fill="#1a2744" stroke="#2a3a55" stroke-width="0.5"/>
<!-- 电缆 (动态高度) -->
<g id="cableGroup">
<rect id="cableBody" x="60" y="410" width="1000" height="40" rx="4" fill="url(#cableGrad)" opacity="0.95"/>
<!-- 电缆芯线暗示 -->
<line id="cableCoreLine" x1="60" y1="430" x2="1060" y2="430" stroke="#e8c35a" stroke-width="0.8" opacity="0.4"/>
</g>
<!-- 切割分离段 (初始隐藏) -->
<rect id="cableCutRight" x="1000" y="410" width="60" height="40" rx="4" fill="url(#cableGrad)" opacity="0"/>
<!-- ===== 滚轮站 1 ===== -->
<g id="rollerStation1" transform="translate(200,0)">
<!-- 弹簧/气缸连接 -->
<line x1="-30" y1="310" x2="-30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="310" x2="30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="-30" y1="500" x2="-30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="500" x2="30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<!-- 弹簧符号 -->
<path d="M-30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M-30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<!-- 上滚轮 -->
<g id="upperRollers1">
<circle cx="-14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="365" x2="-14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="365" x2="14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<!-- 下滚轮 -->
<g id="lowerRollers1">
<circle cx="-14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="465" x2="-14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="465" x2="14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<!-- 锁紧指示环 (初始隐藏) -->
<circle id="lockRing1a" cx="0" cy="380" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<circle id="lockRing1b" cx="0" cy="480" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<text x="0" y="570" text-anchor="middle" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">定心站 I</text>
</g>
<!-- ===== 滚轮站 2 ===== -->
<g id="rollerStation2" transform="translate(380,0)">
<line x1="-30" y1="310" x2="-30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="310" x2="30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="-30" y1="500" x2="-30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="500" x2="30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<path d="M-30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M-30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<g id="upperRollers2">
<circle cx="-14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="365" x2="-14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="365" x2="14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<g id="lowerRollers2">
<circle cx="-14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="465" x2="-14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="465" x2="14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<circle id="lockRing2a" cx="0" cy="380" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<circle id="lockRing2b" cx="0" cy="480" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<text x="0" y="570" text-anchor="middle" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">定心站 II</text>
</g>
<!-- ===== 滚轮站 3 ===== -->
<g id="rollerStation3" transform="translate(560,0)">
<line x1="-30" y1="310" x2="-30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="310" x2="30" y2="360" stroke="#2a3a55" stroke-width="3"/>
<line x1="-30" y1="500" x2="-30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<line x1="30" y1="500" x2="30" y2="540" stroke="#2a3a55" stroke-width="3"/>
<path d="M-30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,320 l5,5 l-10,6 l10,6 l-10,6 l10,6 l-5,5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M-30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<path d="M30,535 l5,-5 l-10,-6 l10,-6 l-10,-6 l10,-6 l-5,-5" fill="none" stroke="#4a6080" stroke-width="1.5"/>
<g id="upperRollers3">
<circle cx="-14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="380" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="365" x2="-14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="365" x2="14" y2="395" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<g id="lowerRollers3">
<circle cx="-14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<circle cx="14" cy="480" r="20" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1.5"/>
<line x1="-14" y1="465" x2="-14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
<line x1="14" y1="465" x2="14" y2="495" stroke="#8fa4bd" stroke-width="0.5" opacity="0.5"/>
</g>
<circle id="lockRing3a" cx="0" cy="380" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<circle id="lockRing3b" cx="0" cy="480" r="26" fill="none" stroke="var(--lock-red)" stroke-width="2" opacity="0"/>
<text x="0" y="570" text-anchor="middle" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">定心站 III</text>
</g>
<!-- ===== 光栅尺 ===== -->
<g id="gratingGroup" transform="translate(720,0)">
<!-- 光栅尺标尺 -->
<rect x="-4" y="295" width="8" height="245" rx="2" fill="#1a2744" stroke="#2a3a55" stroke-width="0.5"/>
<!-- 刻度 -->
<g stroke="#3a5070" stroke-width="0.5" opacity="0.7">
<line x1="-12" y1="310" x2="-4" y2="310"/>
<line x1="-12" y1="330" x2="-4" y2="330"/>
<line x1="-12" y1="350" x2="-4" y2="350"/>
<line x1="-12" y1="370" x2="-4" y2="370"/>
<line x1="-16" y1="390" x2="-4" y2="390"/>
<line x1="-12" y1="410" x2="-4" y2="410"/>
<line x1="-12" y1="430" x2="-4" y2="430"/>
<line x1="-12" y1="450" x2="-4" y2="450"/>
<line x1="-12" y1="470" x2="-4" y2="470"/>
<line x1="-16" y1="490" x2="-4" y2="490"/>
<line x1="-12" y1="510" x2="-4" y2="510"/>
<line x1="-12" y1="530" x2="-4" y2="530"/>
</g>
<!-- 光栅读数头 -->
<rect id="gratingHead" x="-20" y="420" width="16" height="20" rx="2" fill="#2a3a55" stroke="#ff8f00" stroke-width="1"/>
<circle id="gratingDot" cx="-12" cy="430" r="3" fill="#ff8f00" opacity="0.5"/>
<!-- 1m标记线 -->
<line id="gratingTriggerLine" x1="4" y1="295" x2="4" y2="540" stroke="#ff8f00" stroke-width="1" stroke-dasharray="4,4" opacity="0"/>
<text x="14" y="302" fill="#5a6e85" font-size="9" font-family="Share Tech Mono, monospace">光栅尺</text>
<text x="14" y="314" fill="#3a5070" font-size="8" font-family="Share Tech Mono, monospace">分辨率 0.01mm</text>
<!-- 测量值显示 -->
<rect x="10" y="380" width="70" height="24" rx="3" fill="#0d1420" stroke="#2a3a55" stroke-width="0.5"/>
<text id="gratingValue" x="45" y="397" text-anchor="middle" fill="#ff8f00" font-size="13" font-family="Share Tech Mono, monospace">0.000 m</text>
</g>
<!-- ===== 水射流切割站 ===== -->
<g id="cutterGroup" transform="translate(940,0)">
<!-- 密封排污舱 -->
<rect x="-55" y="295" width="110" height="260" rx="6" fill="none" stroke="#1e3050" stroke-width="1.5" stroke-dasharray="6,3"/>
<text x="0" y="580" text-anchor="middle" fill="#3a5070" font-size="8" font-family="Share Tech Mono, monospace">密封排污舱</text>
<!-- 喷嘴支架 -->
<rect x="-10" y="290" width="20" height="80" rx="2" fill="url(#nozzleGrad)" stroke="#4a5f78" stroke-width="1"/>
<!-- 喷嘴 -->
<polygon id="nozzleTip" points="-6,370 6,370 2,385 -2,385" fill="#2a3a50" stroke="#5a7089" stroke-width="1"/>
<circle cx="0" cy="375" r="2.5" fill="#001a33"/>
<!-- 水射流 (初始隐藏) -->
<g id="waterJetGroup" opacity="0">
<line id="waterStream" x1="0" y1="385" x2="0" y2="475" stroke="url(#waterGrad)" stroke-width="2.5" filter="url(#waterGlow)"/>
<!-- 水射流核心 -->
<line x1="0" y1="385" x2="0" y2="475" stroke="#80f0ff" stroke-width="0.8" opacity="0.9"/>
<!-- 飞溅粒子容器 -->
<g id="splashParticles"></g>
</g>
<!-- 扫描移动轨道 -->
<line x1="-40" y1="375" x2="40" y2="375" stroke="#1e3050" stroke-width="1" stroke-dasharray="3,3"/>
<text x="0" y="285" text-anchor="middle" fill="#5a6e85" font-size="9" font-family="Share Tech Mono, monospace">超高压水射流</text>
<text x="0" y="272" text-anchor="middle" fill="#3a5070" font-size="8" font-family="Share Tech Mono, monospace">3000-4000 bar</text>
</g>
<!-- ===== 截面图 (右上角) ===== -->
<g id="crossSectionGroup">
<rect x="1085" y="55" width="300" height="295" rx="6" fill="#080e18" stroke="#1e3050" stroke-width="1"/>
<text x="1235" y="76" text-anchor="middle" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace" letter-spacing="2">截面视图 — 锥面自定心</text>
<!-- 截面中心参考线 -->
<line x1="1100" y1="210" x2="1370" y2="210" stroke="#76ff03" stroke-width="0.8" stroke-dasharray="6,4" opacity="0.4"/>
<text x="1368" y="206" text-anchor="end" fill="#76ff03" font-size="8" font-family="Share Tech Mono, monospace" opacity="0.6">中心</text>
<!-- 截面电缆 -->
<circle id="crossCable" cx="1235" cy="210" r="25" fill="url(#cableGrad)" stroke="#c78c2e" stroke-width="0.5" opacity="0.9"/>
<circle id="crossCableCore" cx="1235" cy="210" r="5" fill="#e8c35a" opacity="0.4"/>
<!-- 4个锥形滚轮 (30度锥角) -->
<g id="crossRollers">
<!-- 左上 -->
<polygon id="crLU" points="1200,175 1210,175 1215,205 1205,205" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1" opacity="0.95"/>
<!-- 左下 -->
<polygon id="crLD" points="1200,245 1210,245 1205,215 1215,215" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1" opacity="0.95"/>
<!-- 右上 -->
<polygon id="crRU" points="1260,175 1270,175 1265,205 1255,205" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1" opacity="0.95"/>
<!-- 右下 -->
<polygon id="crRD" points="1260,245 1270,245 1255,215 1265,215" fill="url(#rollerGrad)" stroke="#8fa4bd" stroke-width="1" opacity="0.95"/>
</g>
<!-- 锥角标注 -->
<path d="M1200,180 A20,20 0 0,1 1210,175" fill="none" stroke="#ff8f00" stroke-width="0.8" opacity="0.7"/>
<text x="1188" y="180" fill="#ff8f00" font-size="8" font-family="Share Tech Mono, monospace" opacity="0.7">30°</text>
<path d="M1270,180 A20,20 0 0,0 1260,175" fill="none" stroke="#ff8f00" stroke-width="0.8" opacity="0.7"/>
<text x="1274" y="180" fill="#ff8f00" font-size="8" font-family="Share Tech Mono, monospace" opacity="0.7">30°</text>
<!-- 弹簧/气缸示意 -->
<line x1="1175" y1="190" x2="1200" y2="190" stroke="#4a6080" stroke-width="1.5"/>
<path d="M1175,190 l3,-4 l6,8 l6,-8 l6,8 l3,-4" fill="none" stroke="#4a6080" stroke-width="1"/>
<line x1="1175" y1="230" x2="1200" y2="230" stroke="#4a6080" stroke-width="1.5"/>
<path d="M1175,230 l3,-4 l6,8 l6,-8 l6,8 l3,-4" fill="none" stroke="#4a6080" stroke-width="1"/>
<line x1="1270" y1="190" x2="1295" y2="190" stroke="#4a6080" stroke-width="1.5"/>
<path d="M1295,190 l-3,-4 l-6,8 l-6,-8 l-6,8 l-3,-4" fill="none" stroke="#4a6080" stroke-width="1"/>
<line x1="1270" y1="230" x2="1295" y2="230" stroke="#4a6080" stroke-width="1.5"/>
<path d="M1295,230 l-3,-4 l-6,8 l-6,-8 l-6,8 l-3,-4" fill="none" stroke="#4a6080" stroke-width="1"/>
<!-- 双向抱拢箭头 -->
<g id="clampArrows" opacity="0.6">
<polygon points="1195,210 1200,206 1200,214" fill="#ff8f00"/>
<polygon points="1275,210 1270,206 1270,214" fill="#ff8f00"/>
</g>
<!-- 直径标注 -->
<line id="crossDimLine" x1="1235" y1="185" x2="1235" y2="235" stroke="#5a6e85" stroke-width="0.5" stroke-dasharray="2,2"/>
<text id="crossDimLabel" x="1252" y="214" fill="#5a6e85" font-size="9" font-family="Share Tech Mono, monospace">φ40</text>
</g>
<!-- ===== 参数面板 ===== -->
<g id="paramPanel">
<rect x="1085" y="370" width="300" height="190" rx="6" fill="#080e18" stroke="#1e3050" stroke-width="1"/>
<text x="1235" y="392" text-anchor="middle" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace" letter-spacing="2">实时参数</text>
<line x1="1100" y1="400" x2="1370" y2="400" stroke="#1e3050" stroke-width="0.5"/>
<text x="1105" y="422" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">水射流压力</text>
<text id="paramPressure" x="1365" y="422" text-anchor="end" fill="#00e5ff" font-size="11" font-family="Share Tech Mono, monospace">3500 bar</text>
<text x="1105" y="446" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">电缆直径</text>
<text id="paramDiameter" x="1365" y="446" text-anchor="end" fill="#c78c2e" font-size="11" font-family="Share Tech Mono, monospace">40 mm</text>
<text x="1105" y="470" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">中心高偏差</text>
<text id="paramCenterDev" x="1365" y="470" text-anchor="end" fill="#76ff03" font-size="11" font-family="Share Tech Mono, monospace">±0.00 mm</text>
<text x="1105" y="494" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">滚轮锥角</text>
<text x="1365" y="494" text-anchor="end" fill="#8fa4bd" font-size="11" font-family="Share Tech Mono, monospace">30°</text>
<text x="1105" y="518" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">当前阶段</text>
<text id="paramPhase" x="1365" y="518" text-anchor="end" fill="#00e676" font-size="11" font-family="Share Tech Mono, monospace">送料定心</text>
<text x="1105" y="546" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">侧向挤压力</text>
<text id="paramForce" x="1365" y="546" text-anchor="end" fill="#76ff03" font-size="11" font-family="Share Tech Mono, monospace">0 N (IFR)</text>
</g>
<!-- ===== IFR理念标注 ===== -->
<g id="ifrAnnotation">
<rect x="1085" y="580" width="300" height="90" rx="6" fill="#080e18" stroke="#76ff03" stroke-width="0.5" opacity="0.8"/>
<text x="1100" y="602" fill="#76ff03" font-size="11" font-weight="700" font-family="Rajdhani, sans-serif">IFR 最终理想解</text>
<text x="1100" y="620" fill="#5a8060" font-size="9" font-family="Share Tech Mono, monospace">矛盾: 夹紧定位 vs 不压扁变形</text>
<text x="1100" y="636" fill="#5a8060" font-size="9" font-family="Share Tech Mono, monospace">解: 锥面几何自定心 → 自适应消除矛盾</text>
<text x="1100" y="652" fill="#5a8060" font-size="9" font-family="Share Tech Mono, monospace"> 水射流代替切刀 → 零侧向力切断</text>
</g>
<!-- 状态指示条 -->
<rect x="80" y="620" width="980" height="32" rx="4" fill="#0b1120" stroke="#1e3050" stroke-width="0.5"/>
<g id="statusBar">
<text x="90" y="641" fill="#5a6e85" font-size="10" font-family="Share Tech Mono, monospace">流程:</text>
<!-- 各阶段标签 -->
<text id="stFeed" x="150" y="641" fill="#00e676" font-size="10" font-family="Share Tech Mono, monospace" opacity="0.3">送料定心</text>
<text x="235" y="641" fill="#2a3a55" font-size="10" font-family="Share Tech Mono, monospace">→</text>
<text id="stMeasure" x="255" y="641" fill="#ff8f00" font-size="10" font-family="Share Tech Mono, monospace" opacity="0.3">光栅测量</text>
<text x="340" y="641" fill="#2a3a55" font-size="10" font-family="Share Tech Mono, monospace">→</text>
<text id="stLock" x="360" y="641" fill="#ff1744" font-size="10" font-family="Share Tech Mono, monospace" opacity="0.3">滚轮锁死</text>
<text x="445" y="641" fill="#2a3a55" font-size="10" font-family="Share Tech Mono, monospace">→</text>
<text id="stCut" x="465" y="641" fill="#00e5ff" font-size="10" font-family="Share Tech Mono, monospace" opacity="0.3">水射流切断</text>
<text x="560" y="641" fill="#2a3a55" font-size="10" font-family="Share Tech Mono, monospace">→</text>
<text id="stUnlock" x="580" y="641" fill="#00e676" font-size="10" font-family="Share Tech Mono, monospace" opacity="0.3">解锁送料</text>
<!-- 进度条 -->
<rect x="680" y="630" width="360" height="8" rx="4" fill="#1a2744"/>
<rect id="progressBar" x="680" y="630" width="0" height="8" rx="4" fill="#00e5ff" opacity="0.7"/>
</g>
<!-- 送料方向箭头 -->
<g id="feedArrow" opacity="0.5">
<polygon points="80,430 95,422 95,438" fill="#00e676"/>
<text x="68" y="460" fill="#5a6e85" font-size="8" font-family="Share Tech Mono, monospace">进料</text>
</g>
<!-- 切断效果指示 -->
<g id="cutIndicator" opacity="0">
<line x1="940" y1="400" x2="940" y2="460" stroke="#00e5ff" stroke-width="1.5" filter="url(#softGlow)"/>
<text x="955" y="400" fill="#00e5ff" font-size="9" font-family="Share Tech Mono, monospace">切断线</text>
</g>
<!-- 无侧向力标注 -->
<g id="noForceLabel" opacity="0">
<text x="980" y="500" fill="#76ff03" font-size="9" font-family="Share Tech Mono, monospace">侧向力 = 0</text>
<text x="980" y="512" fill="#4a6a50" font-size="8" font-family="Share Tech Mono, monospace">无挤压变形</text>
</g>
<!-- 滚轮旋转动画指示 (动态由JS控制) -->
<g id="rotationIndicators"></g>
</svg>
</div>
<!-- 控制面板 -->
<div class="controls">
<div class="ctrl-group" style="flex:1.5">
<label>电缆直径</label>
<div class="value-display"><span id="diameterDisplay">40</span><span class="unit">mm</span></div>
<input type="range" id="diameterSlider" min="5" max="140" value="40" step="1">
<div style="display:flex;justify-content:space-between;font-size:9px;color:#3a5070;font-family:'Share Tech Mono',monospace;margin-top:2px">
<span>5mm 细缆</span><span>140mm 粗缆</span>
</div>
</div>
<div class="ctrl-group" style="flex:1">
<label>水射流压力</label>
<div class="value-display"><span id="pressureDisplay">3500</span><span class="unit">bar</span></div>
<input type="range" id="pressureSlider" min="3000" max="4000" value="3500" step="50">
<div style="display:flex;justify-content:space-between;font-size:9px;color:#3a5070;font-family:'Share Tech Mono',monospace;margin-top:2px">
<span>3000</span><span>4000</span>
</div>
</div>
<div class="ctrl-group" style="flex:0.8">
<label>动画控制</label>
<div class="btn-row">
<button class="btn active" id="btnPlay" onclick="togglePlay()">暂停</button>
<button class="btn" id="btnReset" onclick="resetAnim()">重置</button>
<button class="btn" id="btnStep" onclick="stepPhase()">步进</button>
</div>
<div class="phase-indicator" style="margin-top:12px">
<div class="phase-dot" id="pd0"></div>
<div class="phase-dot" id="pd1"></div>
<div class="phase-dot" id="pd2"></div>
<div class="phase-dot" id="pd3"></div>
<div class="phase-dot" id="pd4"></div>
</div>
<div style="font-size:8px;color:#3a5070;font-family:'Share Tech Mono',monospace;margin-top:4px">
送料 → 测量 → 锁死 → 切断 → 解锁
</div>
</div>
<div class="ctrl-group" style="flex:0.7">
<label>动画速度</label>
<div class="value-display" style="font-size:20px"><span id="speedDisplay">1.0</span><span class="unit">x</span></div>
<input type="range" id="speedSlider" min="0.3" max="3" value="1" step="0.1">
</div>
</div>
</div>
<script>
// ============== 配置 ==============
const CABLE_Y = 430; // 中心线Y坐标
const ROLLER_R = 20; // 滚轮半径
const PHASES = ['FEED','MEASURE','LOCK','CUT','UNLOCK'];
const PHASE_DURATIONS = [4000, 1200, 600, 2800, 800]; // 毫秒
// ============== 状态 ==============
let cableDiameter = 40;
let waterPressure = 3500;
let animSpeed = 1.0;
let playing = true;
let currentPhaseIdx = 0;
let phaseTime = 0;
let lastTimestamp = 0;
let totalCycleTime = PHASE_DURATIONS.reduce((a,b)=>a+b,0);
let feedProgress = 0; // 0-1 送料进度
let measureFlash = 0; // 测量闪烁强度
let lockIntensity = 0; // 锁紧强度 0-1
let cutProgress = 0; // 切割进度 0-1
let unlockProgress = 0; // 解锁进度
let nozzleX = 0; // 喷嘴X偏移
let particles = []; // 飞溅粒子
let rollerAngle = 0; // 滚轮旋转角
// ============== DOM引用 ==============
const svg = document.getElementById('mainSvg');
const cableBody = document.getElementById('cableBody');
const cableCoreLine = document.getElementById('cableCoreLine');
const cableCutRight = document.getElementById('cableCutRight');
const waterJetGroup = document.getElementById('waterJetGroup');
const waterStream = document.getElementById('waterStream');
const splashGroup = document.getElementById('splashParticles');
const gratingValue = document.getElementById('gratingValue');
const gratingDot = document.getElementById('gratingDot');
const gratingHead = document.getElementById('gratingHead');
const gratingTriggerLine = document.getElementById('gratingTriggerLine');
const cutIndicator = document.getElementById('cutIndicator');
const noForceLabel = document.getElementById('noForceLabel');
const crossCable = document.getElementById('crossCable');
const crossCableCore = document.getElementById('crossCableCore');
const crossDimLabel = document.getElementById('crossDimLabel');
const progressBar = document.getElementById('progressBar');
const ifrLine = document.getElementById('ifrLine');
// 滚轮组引用
const rollerStations = [1,2,3].map(i => ({
upper: document.getElementById(`upperRollers${i}`),
lower: document.getElementById(`lowerRollers${i}`),
lockA: document.getElementById(`lockRing${i}a`),
lockB: document.getElementById(`lockRing${i}b`),
}));
// 截面滚轮
const crLU = document.getElementById('crLU');
const crLD = document.getElementById('crLD');
const crRU = document.getElementById('crRU');
const crRD = document.getElementById('crRD');
// 状态文字
const statusTexts = [
document.getElementById('stFeed'),
document.getElementById('stMeasure'),
document.getElementById('stLock'),
document.getElementById('stCut'),
document.getElementById('stUnlock'),
];
const phaseDots = [0,1,2,3,4].map(i => document.getElementById(`pd${i}`));
// 参数面板
const paramPressure = document.getElementById('paramPressure');
const paramDiameter = document.getElementById('paramDiameter');
const paramCenterDev = document.getElementById('paramCenterDev');
const paramPhase = document.getElementById('paramPhase');
const paramForce = document.getElementById('paramForce');
// ============== 工具函数 ==============
function lerp(a,b,t) { return a + (b-a) * Math.min(1, Math.max(0, t)); }
function mapRange(v, inMin, inMax, outMin, outMax) {
return outMin + (v - inMin) / (inMax - inMin) * (outMax - outMin);
}
// 电缆直径 → SVG高度
function diaToSvgHeight(d) { return mapRange(d, 5, 140, 8, 90); }
// 电缆直径 → 截面半径
function diaToCrossRadius(d) { return mapRange(d, 5, 140, 6, 55); }
// ============== 更新函数 ==============
function updateCableVisuals() {
const h = diaToSvgHeight(cableDiameter);
const y = CABLE_Y - h/2;
// 主体电缆
cableBody.setAttribute('y', y);
cableBody.setAttribute('height', h);
cableCoreLine.setAttribute('y1', CABLE_Y);
cableCoreLine.setAttribute('y2', CABLE_Y);
// 切断后右侧段
cableCutRight.setAttribute('y', y);
cableCutRight.setAttribute('height', h);
// 更新滚轮位置
rollerStations.forEach(rs => {
const upperY = CABLE_Y - h/2 - ROLLER_R + 2;
const lowerY = CABLE_Y + h/2 + ROLLER_R - 2;
rs.upper.setAttribute('transform', `translate(0, ${upperY - 380})`);
rs.lower.setAttribute('transform', `translate(0, ${lowerY - 480})`);
rs.lockA.setAttribute('cy', upperY);
rs.lockB.setAttribute('cy', lowerY);
});
// 截面图
const cr = diaToCrossRadius(cableDiameter);
crossCable.setAttribute('r', cr);
crossCableCore.setAttribute('r', Math.max(2, cr * 0.2));
crossDimLabel.textContent = `φ${cableDiameter}`;
// 截面滚轮位置 - 锥面30度自定心
const coneOffset = cr + 8; // 滚轮尖角到中心的距离
const coneWidth = 12;
const coneDepth = cr * 0.8;
// 左上滚轮
crLU.setAttribute('points',
`${1235-coneOffset-coneWidth},${210-coneDepth} ${1235-coneOffset+coneWidth},${210-coneDepth} ${1235-coneOffset+2},${210+4} ${1235-coneOffset-2},${210+4}`);
// 左下滚轮
crLD.setAttribute('points',
`${1235-coneOffset-coneWidth},${210+coneDepth} ${1235-coneOffset+coneWidth},${210+coneDepth} ${1235-coneOffset+2},${210-4} ${1235-coneOffset-2},${210-4}`);
// 右上滚轮
crRU.setAttribute('points',
`${1235+coneOffset+coneWidth},${210-coneDepth} ${1235+coneOffset-coneWidth},${210-coneDepth} ${1235+coneOffset-2},${210+4} ${1235+coneOffset+2},${210+4}`);
// 右下滚轮
crRD.setAttribute('points',
`${1235+coneOffset+coneWidth},${210+coneDepth} ${1235+coneOffset-coneWidth},${210+coneDepth} ${1235+coneOffset-2},${210-4} ${1235+coneOffset+2},${210-4}`);
// 参数面板
paramDiameter.textContent = `${cableDiameter} mm`;
}
function updatePhaseVisuals(dt) {
const phase = PHASES[currentPhaseIdx];
const duration = PHASE_DURATIONS[currentPhaseIdx];
const progress = Math.min(1, phaseTime / duration);
// 重置所有状态文字
statusTexts.forEach((st, i) => {
st.setAttribute('opacity', i === currentPhaseIdx ? '1' : '0.3');
});
phaseDots.forEach((pd, i) => {
pd.className = 'phase-dot';
if (i === currentPhaseIdx) {
const colors = ['active','amber','red','cyan','green'];
pd.classList.add(colors[i]);
}
});
// 进度条
let totalProg = 0;
for (let i = 0; i < currentPhaseIdx; i++) totalProg += PHASE_DURATIONS[i];
totalProg += phaseTime;
const barW = (totalProg / totalCycleTime) * 360;
progressBar.setAttribute('width', barW);
const barColors = ['#00e676','#ff8f00','#ff1744','#00e5ff','#00e676'];
progressBar.setAttribute('fill', barColors[currentPhaseIdx]);
// 阶段特定视觉
switch(phase) {
case 'FEED':
feedProgress = progress;
lockIntensity = lerp(lockIntensity, 0, 0.1);
waterJetGroup.setAttribute('opacity', '0');
cutIndicator.setAttribute('opacity', '0');
noForceLabel.setAttribute('opacity', '0');
gratingTriggerLine.setAttribute('opacity', '0');
gratingDot.setAttribute('opacity', '0.5');
paramPhase.textContent = '送料定心';
paramPhase.setAttribute('fill', '#00e676');
paramForce.textContent = '0 N (IFR)';
// 滚轮旋转
rollerAngle += dt * 0.003 * animSpeed;
break;
case 'MEASURE':
measureFlash = Math.sin(phaseTime * 0.01) * 0.5 + 0.5;
gratingTriggerLine.setAttribute('opacity', measureFlash * 0.8);
gratingDot.setAttribute('opacity', 0.5 + measureFlash * 0.5);
gratingHead.setAttribute('stroke', `rgba(255,143,0,${0.5 + measureFlash * 0.5})`);
paramPhase.textContent = '光栅触发';
paramPhase.setAttribute('fill', '#ff8f00');
// 光栅值递增到1m
const mVal = (progress * 1.0).toFixed(3);
gratingValue.textContent = `${mVal} m`;
if (progress > 0.95) gratingValue.setAttribute('fill', '#ff8f00');
break;
case 'LOCK':
lockIntensity = lerp(lockIntensity, 1, 0.15);
rollerStations.forEach(rs => {
rs.lockA.setAttribute('opacity', lockIntensity);
rs.lockB.setAttribute('opacity', lockIntensity);
});
paramPhase.textContent = '滚轮锁死';
paramPhase.setAttribute('fill', '#ff1744');
paramForce.textContent = '锁紧力 → 0侧向挤压';
break;
case 'CUT':
cutProgress = progress;
waterJetGroup.setAttribute('opacity', '1');
cutIndicator.setAttribute('opacity', lerp(0, 0.8, Math.min(1, progress*3)));
noForceLabel.setAttribute('opacity', lerp(0, 0.9, Math.min(1, progress*2)));
// 喷嘴扫描移动 (从左到右扫过电缆)
const scanRange = diaToSvgHeight(cableDiameter) * 0.6;
nozzleX = Math.sin(progress * Math.PI) * scanRange * 0.3;
// 水射流长度 - 从喷嘴到电缆底部
const h = diaToSvgHeight(cableDiameter);
const streamStart = 385;
const streamEnd = CABLE_Y + h/2 + 5;
waterStream.setAttribute('y1', streamStart);
waterStream.setAttribute('y2', streamEnd);
waterStream.setAttribute('x1', nozzleX);
waterStream.setAttribute('x2', nozzleX);
// 移动喷嘴
document.getElementById('nozzleTip').setAttribute('transform', `translate(${nozzleX},0)`);
// 生成飞溅粒子
if (Math.random() < 0.4) {
spawnParticle(nozzleX, streamEnd);
}
paramPhase.textContent = '水射流切断';
paramPhase.setAttribute('fill', '#00e5ff');
paramPressure.textContent = `${waterPressure} bar`;
// 切断效果 - 电缆逐渐分离
if (progress > 0.4) {
const sep = (progress - 0.4) * 15;
cableCutRight.setAttribute('x', 940 + sep);
cableCutRight.setAttribute('opacity', '1');
cableBody.setAttribute('width', 940 - 60);
}
break;
case 'UNLOCK':
unlockProgress = progress;
lockIntensity = lerp(lockIntensity, 0, 0.15);
rollerStations.forEach(rs => {
rs.lockA.setAttribute('opacity', lockIntensity);
rs.lockB.setAttribute('opacity', lockIntensity);
});
waterJetGroup.setAttribute('opacity', lerp(1, 0, 0.1));
paramPhase.textContent = '解锁继续';
paramPhase.setAttribute('fill', '#00e676');
break;
}
// IFR中心线脉动
const ifrPulse = 0.5 + Math.sin(Date.now() * 0.003) * 0.2;
ifrLine.setAttribute('opacity', ifrPulse);
// 中心高偏差
const dev = (Math.random() * 0.08 - 0.04).toFixed(2);
paramCenterDev.textContent = `±${Math.abs(dev)} mm`;
// 更新粒子
updateParticles(dt);
}
// ============== 粒子系统 ==============
function spawnParticle(x, y) {
const p = {
x: 940 + x,
y: y,
vx: (Math.random() - 0.5) * 4,
vy: Math.random() * 3 + 1,
life: 1.0,
decay: 0.01 + Math.random() * 0.02,
size: 1.5 + Math.random() * 2,
};
particles.push(p);
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('r', p.size);
circle.setAttribute('fill', '#00e5ff');
circle.setAttribute('opacity', '0.8');
circle.setAttribute('cx', p.x);
circle.setAttribute('cy', p.y);
splashGroup.appendChild(circle);
p.el = circle;
}
function updateParticles(dt) {
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.1; // 重力
p.life -= p.decay;
if (p.life <= 0) {
p.el.remove();
particles.splice(i, 1);
} else {
p.el.setAttribute('cx', p.x);
p.el.setAttribute('cy', p.y);
p.el.setAttribute('opacity', p.life * 0.8);
}
}
}
function clearParticles() {
particles.forEach(p => p.el && p.el.remove());
particles = [];
}
// ============== 主动画循环 ==============
function animate(timestamp) {
if (!lastTimestamp) lastTimestamp = timestamp;
const dt = (timestamp - lastTimestamp) * animSpeed;
lastTimestamp = timestamp;
if (playing) {
phaseTime += dt;
const duration = PHASE_DURATIONS[currentPhaseIdx];
if (phaseTime >= duration) {
// 切换到下一阶段
phaseTime = 0;
currentPhaseIdx = (currentPhaseIdx + 1) % PHASES.length;
// 阶段切换时的重置
if (PHASES[currentPhaseIdx] === 'FEED') {
// 新周期开始,重置
feedProgress = 0;
cutProgress = 0;
unlockProgress = 0;
nozzleX = 0;
cableCutRight.setAttribute('opacity', '0');
cableBody.setAttribute('width', 1000);
document.getElementById('nozzleTip').setAttribute('transform', 'translate(0,0)');
gratingValue.textContent = '0.000 m';
gratingValue.setAttribute('fill', '#ff8f00');
clearParticles();
}
if (PHASES[currentPhaseIdx] === 'MEASURE') {
gratingHead.setAttribute('stroke', '#ff8f00');
}
}
updatePhaseVisuals(dt);
}
requestAnimationFrame(animate);
}
// ============== 交互控制 ==============
document.getElementById('diameterSlider').addEventListener('input', function() {
cableDiameter = parseInt(this.value);
document.getElementById('diameterDisplay').textContent = cableDiameter;
updateCableVisuals();
// 动态调整压力 - 细缆降压
if (cableDiameter < 15) {
waterPressure = Math.min(waterPressure, 3200);
document.getElementById('pressureSlider').value = waterPressure;
document.getElementById('pressureDisplay').textContent = waterPressure;
}
});
document.getElementById('pressureSlider').addEventListener('input', function() {
waterPressure = parseInt(this.value);
document.getElementById('pressureDisplay').textContent = waterPressure;
paramPressure.textContent = `${waterPressure} bar`;
});
document.getElementById('speedSlider').addEventListener('input', function() {
animSpeed = parseFloat(this.value);
document.getElementById('speedDisplay').textContent = animSpeed.toFixed(1);
});
function togglePlay() {
playing = !playing;
const btn = document.getElementById('btnPlay');
btn.textContent = playing ? '暂停' : '播放';
btn.classList.toggle('active', playing);
}
function resetAnim() {
currentPhaseIdx = 0;
phaseTime = 0;
feedProgress = 0;
measureFlash = 0;
lockIntensity = 0;
cutProgress = 0;
unlockProgress = 0;
nozzleX = 0;
lastTimestamp = 0;
clearParticles();
cableCutRight.setAttribute('opacity', '0');
cableBody.setAttribute('width', 1000);
waterJetGroup.setAttribute('opacity', '0');
cutIndicator.setAttribute('opacity', '0');
noForceLabel.setAttribute('opacity', '0');
gratingTriggerLine.setAttribute('opacity', '0');
document.getElementById('nozzleTip').setAttribute('transform', 'translate(0,0)');
gratingValue.textContent = '0.000 m';
rollerStations.forEach(rs => {
rs.lockA.setAttribute('opacity', '0');
rs.lockB.setAttribute('opacity', '0');
});
playing = true;
document.getElementById('btnPlay').textContent = '暂停';
document.getElementById('btnPlay').classList.add('active');
}
function stepPhase() {
phaseTime = 0;
currentPhaseIdx = (currentPhaseIdx + 1) % PHASES.length;
if (PHASES[currentPhaseIdx] === 'FEED') {
cableCutRight.setAttribute('opacity', '0');
cableBody.setAttribute('width', 1000);
clearParticles();
}
}
// ============== 初始化 ==============
updateCableVisuals();
requestAnimationFrame(animate);
</script>
</body>
</html>
实现说明:
视觉设计:采用深色工业仪表盘风格,精确工程网格背景,以铜色表示电缆、钢灰色表示机械结构、青色标识水射流、石灰绿(#76ff03)标识 IFR 理想中心面——这条虚线始终贯穿全场并轻柔脉动,视觉上强化"中心面恒定不变"这一核心 IFR 思想。
核心动画逻辑:五阶段状态机循环——送料定心 → 光栅测量 → 滚轮锁死 → 水射流切断 → 解锁继续。每阶段有独立的视觉反馈:滚轮旋转、光栅尺读数递增并闪烁、锁紧环红色高亮、水射流喷射与飞溅粒子、电缆分离动画。
IFR 理念突出:
- 中心参考线永不移动,直径变化时滚轮自适应开合但中心面恒定;
- 水射流始终瞄准该理想面,零侧向力切断(标注"侧向力 = 0");
- 右侧面板明确列出矛盾与消解逻辑。
交互性:电缆直径滑块(5-140mm)实时改变电缆粗细和滚轮位置,直观体验"无论线径如何,中心高度一致";水射流压力滑块;播放/暂停/步进/重置控制;动画速度调节。截面图同步展示锥面滚轮自适应收放。
积分规则:第一轮对话扣减6分,后续每轮扣4分
等待动画代码生成...
