独立渲染引擎就绪引擎就绪
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.75);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部紧凑标题与状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(56, 189, 248, 0.15);
color: var(--accent-cyan);
border: 1px solid var(--accent-cyan);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 - 最大化空间,绝不遮挡 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部轻量交互卡片,靠边对齐 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 16px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
/* 动画类 */
.rot-cw {
transform-origin: center;
animation: spin 3s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* 微小振动特效 */
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">IFR 最终理想解</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">抖动频率: <span class="val" id="val-freq">6.5 Hz</span></div>
<div class="badge">薯皮破损率: <span class="val">< 0.1%</span></div>
<div class="badge">明薯率: <span class="val">99.4%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<!-- 柔和发光滤镜 -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- 1. 背景网格标尺参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="100" y1="420" x2="1150" y2="420" /> <!-- 地表线参考 -->
<line x1="100" y1="490" x2="1150" y2="490" /> <!-- 深度参考线 -->
</g>
<!-- 2. 地下原状土层与地表 -->
<g id="ground-layer">
<!-- 未开垦地表 -->
<path d="M 50 420 L 320 420 L 320 580 L 50 580 Z" fill="url(#soilGrad)" />
<rect x="50" y="420" width="270" height="160" fill="url(#soilTexture)" />
<!-- 地表草皮/硬土线 -->
<path d="M 50 420 L 320 420" stroke="#10b981" stroke-width="3" stroke-dasharray="8 4" opacity="0.6"/>
<!-- 漏土回填区 (设备下方) -->
<path d="M 370 520 Q 550 490 850 490 L 850 580 L 370 580 Z" fill="#451a03" opacity="0.7"/>
<text x="600" y="550" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 原生红薯埋藏层示意(等待被挖掘) -->
<g id="embedded-potatoes" opacity="0.75">
<ellipse cx="140" cy="460" rx="20" ry="14" fill="#f59e0b" transform="rotate(-15 140 460)" />
<ellipse cx="230" cy="465" rx="22" ry="15" fill="#f59e0b" transform="rotate(20 230 465)" />
<ellipse cx="290" cy="455" rx="19" ry="13" fill="#f59e0b" transform="rotate(-5 290 455)" />
</g>
<!-- 4. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(240, 370)">
<line x1="0" y1="0" x2="-30" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-30" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<!-- 轮子旋转主体 -->
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<!-- 深度锁定标识 -->
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲与偏心轮机构 -->
<g id="vibrating-blade-group" class="vibrating">
<!-- 铲刃与铲背 (入土角 20°) -->
<path d="M 310 495 L 390 470 L 450 415 L 430 405 L 375 455 L 295 480 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<!-- 锐化铲尖 -->
<polygon points="295,480 325,488 310,495" fill="#e0f2fe" />
<!-- 偏心振动凸轮 -->
<g transform="translate(410, 440)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="320" y="525" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两级杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<!-- 链条运动导轨与转轮 -->
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一级主动轮/从动轮 -->
<circle cx="450" cy="420" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="620" cy="310" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二级抖动轮与末端轮 -->
<circle cx="650" cy="300" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="820" cy="210" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架连线 -->
<path d="M 450 420 L 620 310" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 450 435 L 620 325" stroke="#1e293b" stroke-width="3"/>
<path d="M 650 300 L 820 210" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 650 315 L 820 225" stroke="#1e293b" stroke-width="3"/>
<!-- 杆条缝隙标示 (35mm) -->
<text x="510" y="345" fill="#94a3b8" font-size="10" transform="rotate(-32 510 345)">间距 35mm 杆条抖动链 (土落薯留)</text>
<text x="695" y="235" fill="#94a3b8" font-size="10" transform="rotate(-27 695 235)">二级均质筛分段 (0.9m/s)</text>
</g>
<!-- [D] 柔性橡胶缓冲溜槽 (35° 倾角) -->
<g id="buffer-chute" transform="translate(830, 215)">
<!-- 溜槽外壁骨架 -->
<path d="M 0 0 L 85 70 L 100 130" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<!-- 柔性橡胶衬垫层 (绿色柔光) -->
<path d="M -3 -3 L 82 67 L 97 127" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<!-- 阻尼波纹减速标记 -->
<line x1="25" y1="15" x2="35" y2="30" stroke="#a7f3d0" stroke-width="2" stroke-linecap="round"/>
<line x1="55" y1="40" x2="65" y2="55" stroke="#a7f3d0" stroke-width="2" stroke-linecap="round"/>
<text x="50" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="50" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [E] 收集料箱 (底部减振垫 + 导流斜板) -->
<g id="collection-box" transform="translate(920, 330)">
<!-- 料箱外壳 -->
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<!-- 内置 10mm 橡胶减振底垫 -->
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<!-- 导流斜板 (引导平滑堆叠) -->
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
<text x="55" y="195" fill="#64748b" font-size="9">消除末端跌落冲击 (≤250mm)</text>
</g>
<!-- 5. 动态物理粒子与红薯流动层 (由 JavaScript 实时驱动渲染) -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<!-- 6. 关键工艺流向引导光效线 -->
<g id="process-flow-arrows" opacity="0.8">
<!-- 挖掘抬升力流线 -->
<path d="M 300 480 Q 370 450 440 420" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
<!-- 分离抖动能量波纹 -->
<g id="vibe-waves" stroke="#f59e0b" stroke-width="1.5" fill="none" opacity="0.6">
<circle cx="530" cy="365" r="8"/>
<circle cx="730" cy="255" r="8"/>
</g>
</g>
</svg>
</main>
<!-- 底部轻量信息与控制栏 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>定深抬起与分选</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>完整薯块 (土落薯留)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>细碎土壤脱落回填</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #10b981;"></div>
<span>柔性缓冲消能路径</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
// 物理仿真参数与物料流控制器
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let spawnInterval = 45; // 帧间隔
// 活跃的颗粒集合
const potatoes = [];
const soilParticles = [];
const collectedPotatoes = [];
// 运动路径关键坐标点
// Path 1: 振动铲入料 (295, 480) -> (450, 420)
// Path 2: 一级抖动链 (450, 420) -> (620, 310)
// Path 3: 二级筛分 (650, 300) -> (820, 210)
// Path 4: 柔性缓冲溜槽滑动 (820, 210) -> (905, 280) -> (925, 340)
// Path 5: 进入料箱堆叠 (940~1080, 430~470)
class Potato {
constructor() {
this.progress = 0; // 0.0 到 1.0
this.rx = 13 + Math.random() * 5;
this.ry = 9 + Math.random() * 4;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 4;
this.offsetY = (Math.random() - 0.5) * 8;
// 创建 SVG DOM
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#d97706");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0035 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.2) {
// 铲刀抬起阶段
const t = p / 0.2;
x = 295 + (450 - 295) * t;
y = 480 + (420 - 480) * t + Math.sin(t * 20) * 2;
} else if (p < 0.5) {
// 一级抖动链 (上下波浪抖动)
const t = (p - 0.2) / 0.3;
x = 450 + (620 - 450) * t;
y = 420 + (310 - 420) * t + Math.sin(t * 30) * 3.5 + this.offsetY;
} else if (p < 0.75) {
// 二级筛分 (微幅抖动)
const t = (p - 0.5) / 0.25;
x = 640 + (820 - 640) * t;
y = 305 + (210 - 305) * t + Math.sin(t * 25) * 2 + this.offsetY;
} else if (p < 0.9) {
// 35° 柔性溜槽缓冲滑动 (斜率平滑)
const t = (p - 0.75) / 0.15;
x = 820 + (915 - 820) * t;
y = 210 + (335 - 210) * (t * t); // 重力减速曲线
} else if (p < 1.0) {
// 料箱内缓速滚落并到位
const t = (p - 0.9) / 0.1;
const targetSlot = Math.min(1060, 945 + (potatoes.length % 7) * 16);
x = 915 + (targetSlot - 915) * t;
y = 335 + (460 - 335) * t;
} else {
// 最终静止于料箱
this.isDone = true;
x = 945 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
class SoilParticle {
constructor(x, y) {
this.x = x + (Math.random() - 0.5) * 20;
this.y = y + (Math.random() - 0.5) * 10;
this.vx = (Math.random() - 0.5) * 1.5;
this.vy = 1.2 + Math.random() * 2.5; // 重力下落速度
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.8");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.12 * timeScale; // 重力加速度
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.8));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
// 持续生成薯块
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato());
}
// 在抖动链区域连续产生细碎漏土粒子
if (Math.random() < 0.7 * timeScale) {
// 一级筛漏土
const t1 = Math.random();
const s1x = 450 + (620 - 450) * t1;
const s1y = 420 + (310 - 420) * t1 + 8;
soilParticles.push(new SoilParticle(s1x, s1y));
// 二级筛漏土
const t2 = Math.random();
const s2x = 650 + (800 - 650) * t2;
const s2y = 300 + (215 - 300) * t2 + 8;
soilParticles.push(new SoilParticle(s2x, s2y));
}
// 更新薯块状态
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
// 料箱满后自动循环复位,保持长时间运转美观
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 540) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互绑定
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const freq = (6.5 * timeScale).toFixed(1);
document.getElementById('val-freq').innerText = `${freq} Hz`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(18, 55 - density * 10);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 页面加载完成后自动无缝启动
window.addEventListener('DOMContentLoaded', () => {
// 预先填入3个行进中的薯块,使得初始状态丰满自然
const initialP1 = new Potato(); initialP1.progress = 0.25; potatoes.push(initialP1);
const initialP2 = new Potato(); initialP2.progress = 0.55; potatoes.push(initialP2);
const initialP3 = new Potato(); initialP3.progress = 0.82; potatoes.push(initialP3);
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.75);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部紧凑标题与状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(56, 189, 248, 0.15);
color: var(--accent-cyan);
border: 1px solid var(--accent-cyan);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部轻量交互卡片 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 16px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
/* 动画类 */
.rot-cw {
transform-origin: center;
animation: spin 3s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* 微小振动特效 */
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">IFR 最终理想解</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">抖动频率: <span class="val" id="val-freq">6.5 Hz</span></div>
<div class="badge">薯皮破损率: <span class="val">< 0.1%</span></div>
<div class="badge">明薯率: <span class="val">99.4%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<!-- 柔和发光滤镜 -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic"補充in2="blur" operator="over" />
</filter>
</defs>
<!-- 1. 背景网格标尺参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" /> <!-- 地表线参考 -->
<line x1="20" y1="490" x2="1150" y2="490" /> <!-- 深度参考线 15cm -->
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<!-- 未开垦地表主土层(左侧连续来料区) -->
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<!-- 底层硬土底盘(未扰动区) -->
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/草皮线 -->
<path d="M 20 420 L 290 420" stroke="#10b981" stroke-width="3" stroke-dasharray="8 4" opacity="0.7"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 (设备下方自然落土) -->
<path d="M 370 480 Q 550 460 850 460 L 850 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="560" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 原生埋藏土层中的红薯 (来料动画容器) -->
<g id="underground-field-potatoes"></g>
<!-- 4. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<!-- 轮子旋转主体 -->
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲与偏心轮机构 -->
<g id="vibrating-blade-group" class="vibrating">
<!-- 铲刃与铲背 (入土角 20°) -->
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<!-- 锐化入土铲尖 -->
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<!-- 偏心振动凸轮 -->
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·铲刃入土抬升整层土垡</text>
</g>
<!-- [C] 两级杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<!-- 链条运动导轨与转轮 -->
<g id="rollers" stroke="#475569" stroke-width="4">
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="620" cy="305" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="650" cy="295" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="820" cy="210" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架连线 -->
<path d="M 440 405 L 620 305" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 440 420 L 620 320" stroke="#1e293b" stroke-width="3"/>
<path d="M 650 295 L 820 210" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 650 310 L 820 225" stroke="#1e293b" stroke-width="3"/>
<!-- 杆条缝隙标示 (35mm) -->
<text x="495" y="340" fill="#94a3b8" font-size="10" transform="rotate(-30 495 340)">间距 35mm 杆条抖动链 (土落薯留)</text>
<text x="695" y="235" fill="#94a3b8" font-size="10" transform="rotate(-27 695 235)">二级均质筛分段 (0.9m/s)</text>
</g>
<!-- [D] 柔性橡胶缓冲溜槽 (35° 倾角) -->
<g id="buffer-chute" transform="translate(830, 215)">
<path d="M 0 0 L 85 70 L 100 130" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 82 67 L 97 127" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="45" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="45" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [E] 收集料箱 (底部减振垫 + 导流斜板) -->
<g id="collection-box" transform="translate(920, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
<text x="55" y="195" fill="#64748b" font-size="9">消除末端跌落冲击 (≤250mm)</text>
</g>
<!-- 5. 动态物理粒子与红薯流动层 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<!-- 6. 铲尖切削力与土层起拔动态流向引导线 -->
<g id="process-flow-arrows" opacity="0.8">
<!-- 铲刃切土入土导向箭头 -->
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<!-- 沿铲面向上抬升土垡流线 -->
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部轻量信息与控制栏 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与分选</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>埋地土豆 → 完整出土</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>碎土解体漏回田间</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #10b981;"></div>
<span>柔性缓冲消能收集</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
// 物理仿真参数与物料流控制器
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let spawnInterval = 48; // 帧间隔
// 活跃的颗粒集合
const potatoes = [];
const soilParticles = [];
const collectedPotatoes = [];
// 完整作业过程阶段定义:
// 阶段0 (p: 0.00 ~ 0.18): 地下埋藏期 (x: 40 -> 265, y: 450~460 深度 15cm 原土层中随行进逼近铲尖)
// 阶段1 (p: 0.18 ~ 0.30): 铲尖破土抬起土垡 (从地下 (265, 470) 沿 20° 振动铲面被托起至 (440, 405)),包裹泥土剧烈振动
// 阶段2 (p: 0.30 ~ 0.55): 一级抖动链碎土分选 (440, 405) -> (620, 305),土块脱落漏下
// 阶段3 (p: 0.55 ~ 0.75): 二级筛分均化 (640, 295) -> (820, 210)
// 阶段4 (p: 0.75 ~ 0.90): 柔性缓冲溜槽 35° 顺滑滑落 (820, 210) -> (915, 335)
// 阶段5 (p: 0.90 ~ 1.00): 进入料箱沿导流板就位 (945~1060, 460)
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 5;
this.ry = 9 + Math.random() * 4;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 3;
this.offsetY = (Math.random() - 0.5) * 6;
this.embedDepth = 448 + Math.random() * 16; // 地下埋藏纵坐标 (约15cm深度)
// 创建 SVG 薯块元素
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 【阶段0:土层埋藏与逼近挖掘区】
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
// 未挖掘时在土中略带暗色滤镜,随逼近渐明
this.el.setAttribute("opacity", "0.85");
this.el.setAttribute("stroke", "#78350f");
} else if (p < 0.30) {
// 【阶段1:铲尖切削入土与起垡抬升】土豆从地下被振动铲刃从底部完整铲起并向上托举
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
// 伴随高频微振动
y = bladeBaseY - this.ry * 0.8 + Math.sin(t * 24) * 2;
this.el.setAttribute("opacity", "1.0");
this.el.setAttribute("stroke", "#d97706");
} else if (p < 0.55) {
// 【阶段2:一级抖动链 (土垡碎裂,土落薯留)】
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
y = 405 + (305 - 405) * t + Math.sin(t * 28) * 3.5 + this.offsetY;
} else if (p < 0.75) {
// 【阶段3:二级筛分 (均布与微幅抖动)】
const t = (p - 0.55) / 0.20;
x = 640 + (820 - 640) * t;
y = 295 + (210 - 295) * t + Math.sin(t * 22) * 2 + this.offsetY;
} else if (p < 0.90) {
// 【阶段4:35° 柔性橡胶溜槽低动能滑动】
const t = (p - 0.75) / 0.15;
x = 820 + (915 - 820) * t;
y = 210 + (335 - 210) * (t * t); // 平滑降速曲线
} else if (p < 1.0) {
// 【阶段5:料箱内部顺导流板平滑堆放】
const t = (p - 0.90) / 0.10;
const targetSlot = Math.min(1060, 945 + (potatoes.length % 7) * 16);
x = 915 + (targetSlot - 915) * t;
y = 335 + (460 - 335) * t;
} else {
// 最终静止于料箱
this.isDone = true;
x = 945 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
class SoilParticle {
constructor(x, y, isCuttingBurst = false) {
this.x = x + (Math.random() - 0.5) * (isCuttingBurst ? 12 : 20);
this.y = y + (Math.random() - 0.5) * (isCuttingBurst ? 8 : 10);
// 铲尖破碎时具有向右上的初速度,筛分时主要是向下重力坠落
this.vx = isCuttingBurst ? (1.5 + Math.random() * 2.0) : ((Math.random() - 0.5) * 1.5);
this.vy = isCuttingBurst ? (-1.5 - Math.random() * 2.0) : (1.2 + Math.random() * 2.5);
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.85");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.14 * timeScale; // 重力加速度
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.85));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
// 持续生成地下待挖掘土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 1. 铲尖切土起垡处的土块破碎喷溅效果
if (Math.random() < 0.65 * timeScale) {
const cutX = 275 + Math.random() * 25;
const cutY = 465 + Math.random() * 10;
soilParticles.push(new SoilParticle(cutX, cutY, true));
}
// 2. 抖动链筛分区的自然漏土粒子
if (Math.random() < 0.7 * timeScale) {
// 一级筛漏土
const t1 = Math.random();
const s1x = 440 + (620 - 440) * t1;
const s1y = 405 + (305 - 405) * t1 + 8;
soilParticles.push(new SoilParticle(s1x, s1y, false));
// 二级筛漏土
const t2 = Math.random();
const s2x = 650 + (800 - 650) * t2;
const s2y = 295 + (215 - 295) * t2 + 8;
soilParticles.push(new SoilParticle(s2x, s2y, false));
}
// 更新薯块状态
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
// 料箱满后自动循环复位,保持长时间运转美观
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互绑定
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const freq = (6.5 * timeScale).toFixed(1);
document.getElementById('val-freq').innerText = `${freq} Hz`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 页面加载完成后自动无缝启动
window.addEventListener('DOMContentLoaded', () => {
// 预先填入涵盖全生命周期的土豆(含地下待挖、铲尖起垡、抖动筛分、滑入料箱)
potatoes.push(new Potato(0.06)); // 地下埋藏逼近中
potatoes.push(new Potato(0.22)); // 正在被挖掘铲起
potatoes.push(new Potato(0.42)); // 抖动链一级碎土
potatoes.push(new Potato(0.68)); // 二级筛分
potatoes.push(new Potato(0.85)); // 柔性滑槽缓冲
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 2.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 2.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
/* 弹性梳齿轻微拂动 */
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(4deg); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">辊面间隙: <span class="val">40 mm (只夹秧不夹薯)</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<text x="475" y="345" fill="#94a3b8" font-size="10" transform="rotate(-29 475 345)">杆条抖动链 (35mm 净间距 · 土落)</text>
</g>
<!-- [NEW] [D] 弹性梳齿挡帘 (上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(735, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<!-- 悬挂的弹性梳齿群 -->
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="62" />
<line x1="9" y1="0" x2="13" y2="60" />
<line x1="15" y1="0" x2="20" y2="64" />
<line x1="21" y1="0" x2="27" y2="58" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [NEW] [E] 对转螺旋棱橡胶排秧辊机构 (条件/空间分离核心) -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="830" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧</text>
<!-- 上螺旋辊 (顺时针转动咬入, 直径 150mm) -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="28" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<!-- 螺旋棱花纹 -->
<path d="M -22 -14 Q 0 0 22 14" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -14 22 Q 0 0 14 -22" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="6" fill="#0f172a"/>
</g>
<text x="36" y="-6" fill="#86efac" font-size="9">上对转辊 80 r/min →</text>
</g>
<!-- 下螺旋辊 (逆时针转动对咬, 留出 40mm 辊缝与辊下薯通道) -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<!-- 螺旋棱花纹 -->
<path d="M -18 12 Q 0 0 18 -12" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -12 -18 Q 0 0 12 18" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<text x="34" y="6" fill="#86efac" font-size="9">← 下对转辊 (间隙 40mm)</text>
</g>
<!-- 只夹秧·不夹薯 原理标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 薯块顺畅滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 (35° 倾角) -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (底部减振垫 + 导流斜板) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
</g>
<!-- 动态层:土壤、薯块、薯秧与排秧粒子 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-vines"></g>
<g id="dynamic-potatoes"></g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>薯块 (从辊下间隙滚过)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>薯秧 (被螺旋棱咬住横向抛出)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>碎土漏回田间</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
// 仿真控制器
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 46;
const potatoes = [];
const vines = [];
const soilParticles = [];
const collectedPotatoes = [];
// 薯块运动轨迹类
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 5;
this.ry = 9 + Math.random() * 4;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 3;
this.offsetY = (Math.random() - 0.5) * 6;
this.embedDepth = 448 + Math.random() * 16;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 地下埋藏推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.85");
this.el.setAttribute("stroke", "#78350f");
} else if (p < 0.30) {
// 铲尖切土与起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.8 + Math.sin(t * 24) * 2;
this.el.setAttribute("opacity", "1.0");
this.el.setAttribute("stroke", "#d97706");
} else if (p < 0.55) {
// 抖动链碎土分选
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
y = 405 + (310 - 405) * t + Math.sin(t * 28) * 3.5 + this.offsetY;
} else if (p < 0.73) {
// 逼近排秧辊下方
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
y = 310 + (235 - 310) * t + Math.sin(t * 20) * 2 + this.offsetY;
} else if (p < 0.83) {
// 【空间/条件分离】薯块短圆光滑,从螺旋辊下方 40mm 间隙顺滑滚过,被下辊表面轻推向前
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 235 + (245 - 235) * t + Math.sin(t * Math.PI) * 4;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽低动能滑动
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 料箱就位
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 【新增】薯秧纤维分离运动类 (展示被梳齿挑起、被辊缝咬住、横向抛出的完整机理)
class VineStrand {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.length = 35 + Math.random() * 20;
this.waveOffset = Math.random() * 10;
// 创建波浪状薯秧曲线
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#22c55e");
this.el.setAttribute("stroke-width", "3");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
vineGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
const p = this.progress;
let x, y, angle = 0, opacity = 1.0;
if (p < 0.20) {
// 随地表和挖掘起垡进入
const t = p / 0.20;
x = 100 + (320 - 100) * t;
y = 415 + (440 - 415) * t;
angle = 15;
} else if (p < 0.65) {
// 沿抖动链上层被输送,被弹性梳齿逐渐挑起
const t = (p - 0.20) / 0.45;
x = 320 + (745 - 320) * t;
y = 440 + (210 - 440) * t - (t > 0.6 ? (t - 0.6) * 60 : 0); // 梳齿挑起段
angle = -20 - t * 15;
} else if (p < 0.85) {
// 【核心创新点】被上下对转螺旋辊缝 (780, 178) 咬住,产生轴向推力向机侧上方排秧口抛出
const t = (p - 0.65) / 0.20;
x = 745 + (870 - 745) * t;
y = 195 + (90 - 195) * Math.sin(t * (Math.PI / 2));
angle = -45 - t * 45;
this.el.setAttribute("stroke", "#86efac"); // 咬住时高亮
} else if (p < 1.0) {
// 从机侧排秧口抛离机外田间
const t = (p - 0.85) / 0.15;
x = 870 + 60 * t;
y = 90 + 50 * (t * t);
angle = -90 - t * 30;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
// 生成卷曲草茎的贝塞尔形态
const rad = angle * Math.PI / 180;
const dx = Math.cos(rad) * (this.length / 2);
const dy = Math.sin(rad) * (this.length / 2);
const d = `M ${x - dx} ${y - dy} Q ${x + Math.sin(this.progress * 20) * 8} ${y + Math.cos(this.progress * 20) * 8} ${x + dx} ${y + dy}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", opacity);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 碎土粒子
class SoilParticle {
constructor(x, y, isCuttingBurst = false) {
this.x = x + (Math.random() - 0.5) * (isCuttingBurst ? 12 : 20);
this.y = y + (Math.random() - 0.5) * (isCuttingBurst ? 8 : 10);
this.vx = isCuttingBurst ? (1.5 + Math.random() * 2.0) : ((Math.random() - 0.5) * 1.5);
this.vy = isCuttingBurst ? (-1.5 - Math.random() * 2.0) : (1.2 + Math.random() * 2.5);
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.85");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.14 * timeScale;
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.85));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
// 生成薯块
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成薯秧纤维
if (vineSpawnCounter >= spawnInterval * 1.4) {
vineSpawnCounter = 0;
vines.push(new VineStrand(0));
}
// 铲尖破碎土与抖动漏土
if (Math.random() < 0.65 * timeScale) {
soilParticles.push(new SoilParticle(275 + Math.random() * 25, 465 + Math.random() * 10, true));
}
if (Math.random() < 0.7 * timeScale) {
const t1 = Math.random();
soilParticles.push(new SoilParticle(440 + (600 - 440) * t1, 405 + (315 - 405) * t1 + 8, false));
const t2 = Math.random();
soilParticles.push(new SoilParticle(630 + (760 - 630) * t2, 305 + (230 - 305) * t2 + 8, false));
}
// 更新薯块
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新薯秧
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热播放
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.06));
potatoes.push(new Potato(0.25));
potatoes.push(new Potato(0.48));
potatoes.push(new Potato(0.74)); // 正在从辊下间隙滚过
potatoes.push(new Potato(0.88));
vines.push(new VineStrand(0.35));
vines.push(new VineStrand(0.72)); // 正在被螺旋辊咬住抛出
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 2.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 2.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.15s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(4deg); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">链面状态: <span class="val">平稳托持微振</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<!-- 密集杆条排示意 (强化托持感) -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="475" y="345" fill="#94a3b8" font-size="10" transform="rotate(-29 475 345)">杆条抖动链 (35mm 净间距 · 贴面平稳微振托送)</text>
</g>
<!-- [D] 弹性梳齿挡帘 (上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(735, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="62" />
<line x1="9" y1="0" x2="13" y2="60" />
<line x1="15" y1="0" x2="20" y2="64" />
<line x1="21" y1="0" x2="27" y2="58" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 对转螺旋棱橡胶排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="830" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧</text>
<!-- 上螺旋辊 -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="28" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -22 -14 Q 0 0 22 14" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -14 22 Q 0 0 14 -22" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="6" fill="#0f172a"/>
</g>
<text x="36" y="-6" fill="#86efac" font-size="9">上对转辊 80 r/min →</text>
</g>
<!-- 下螺旋辊 -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 12 Q 0 0 18 -12" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -12 -18 Q 0 0 12 18" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<text x="34" y="6" fill="#86efac" font-size="9">← 下对转辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 薯块顺畅滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
</g>
<!-- 动态层:土壤漏落、底层薯块托运、表层茎叶抖动上移与排秧 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>薯块 (贴链面平稳微振上移)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (浮于表层抖动后排秧)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>碎土漏回田间</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 46;
const potatoes = [];
const vines = [];
const soilParticles = [];
const collectedPotatoes = [];
// 薯块类:贴紧链面稳定输送,小幅微振,绝不乱飞
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 4;
this.ry = 9 + Math.random() * 3;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 1.5;
this.embedDepth = 452 + Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 地下原状土层推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.85");
this.el.setAttribute("stroke", "#78350f");
} else if (p < 0.30) {
// 铲尖切入与平稳起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 18) * 0.8;
this.el.setAttribute("opacity", "1.0");
this.el.setAttribute("stroke", "#d97706");
} else if (p < 0.55) {
// 一级杆条抖动链:紧贴链面平稳上移,受控小幅微振 (振幅 ≤1.2px)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 36) * 1.2;
} else if (p < 0.73) {
// 二级杆条筛面平稳输送
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 32) * 1.0;
} else if (p < 0.83) {
// 从对转橡胶辊下方 40mm 间隙安全滚过
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 1.5;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽平滑滑动
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 进入料箱平稳就位
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 【新增/增强】带有真实茎秆与绿叶构造的复合薯秧体:浮在土薯上方,明显振动上移并被排秧辊咬出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
// 创建 SVG 组合节点包含主茎与叶片
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
// 弯曲主茎
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
// 叶片 1
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
// 叶片 2
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
// 地表植被随土垡被挖掘铲起
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.65) {
// 浮在杆条链上方:显著波浪式振动上移
const t = (p - 0.20) / 0.45;
x = 320 + (745 - 320) * t;
// 位于土豆层上侧 (y 比链条高 18~28px),呈现生动的波浪振颤
const vibHeight = Math.sin(t * 26) * 4.5 + Math.cos(t * 40) * 2;
const chainY = 425 + (205 - 425) * t;
const liftByComb = t > 0.65 ? (t - 0.65) * 65 : 0; // 梳齿挑起
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 30) * 8;
} else if (p < 0.85) {
// 被对转螺旋排秧辊咬住向机侧排秧口抛送
const t = (p - 0.65) / 0.20;
x = 745 + (870 - 745) * t;
y = 190 + (90 - 190) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 50;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
// 飞向机侧外
const t = (p - 0.85) / 0.15;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 25;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
// 动态绘制带韧性波浪的主茎秆
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 24) * 6;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
// 动态定位两片绿叶
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 碎土粒子
class SoilParticle {
constructor(x, y, isCuttingBurst = false) {
this.x = x + (Math.random() - 0.5) * (isCuttingBurst ? 12 : 20);
this.y = y + (Math.random() - 0.5) * (isCuttingBurst ? 8 : 10);
this.vx = isCuttingBurst ? (1.5 + Math.random() * 2.0) : ((Math.random() - 0.5) * 1.5);
this.vy = isCuttingBurst ? (-1.5 - Math.random() * 2.0) : (1.2 + Math.random() * 2.5);
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.85");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.14 * timeScale;
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.85));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
// 生成薯块
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成茎秆与叶片
if (vineSpawnCounter >= spawnInterval * 1.1) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 铲尖破碎土与筛面漏土
if (Math.random() < 0.65 * timeScale) {
soilParticles.push(new SoilParticle(275 + Math.random() * 25, 465 + Math.random() * 10, true));
}
if (Math.random() < 0.7 * timeScale) {
const t1 = Math.random();
soilParticles.push(new SoilParticle(440 + (600 - 440) * t1, 405 + (315 - 405) * t1 + 8, false));
const t2 = Math.random();
soilParticles.push(new SoilParticle(630 + (760 - 630) * t2, 305 + (230 - 305) * t2 + 8, false));
}
// 更新薯块
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新薯秧茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.06));
potatoes.push(new Potato(0.24));
potatoes.push(new Potato(0.44));
potatoes.push(new Potato(0.66));
potatoes.push(new Potato(0.82));
vines.push(new VineEntity(0.12));
vines.push(new VineEntity(0.38)); // 杆条振动上移中
vines.push(new VineEntity(0.70)); // 正在被挑起与咬住
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 2.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 2.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.15s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(4deg); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 (螺距 50mm 动态走丝) */
.screw-axial-flow {
animation: screwFlow 1.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">链面状态: <span class="val">平稳托持微振</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="475" y="345" fill="#94a3b8" font-size="10" transform="rotate(-29 475 345)">杆条抖动链 (35mm 净间距 · 贴面平稳微振托送)</text>
</g>
<!-- [D] 弹性梳齿挡帘 (上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(735, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="62" />
<line x1="9" y1="0" x2="13" y2="60" />
<line x1="15" y1="0" x2="20" y2="64" />
<line x1="21" y1="0" x2="27" y2="58" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图:对转螺旋棱橡胶排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 830 110 880 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="830" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧</text>
<!-- 上螺旋辊 -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="28" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -22 -14 Q 0 0 22 14" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -14 22 Q 0 0 14 -22" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="6" fill="#0f172a"/>
</g>
<text x="36" y="-6" fill="#86efac" font-size="9">上对转辊 80 r/min →</text>
</g>
<!-- 下螺旋辊 -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 12 Q 0 0 18 -12" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<path d="M -12 -18 Q 0 0 12 18" stroke="#86efac" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<text x="34" y="6" fill="#86efac" font-size="9">← 下对转辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 薯块顺畅滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
</g>
<!-- 动态层:土壤漏落、底层薯块托运、表层茎叶抖动上移与排秧 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [NEW] [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<!-- 连线引导框 (从主体螺旋辊引出虚线连至放大镜) -->
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<!-- 特写圆镜背景与视口 -->
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<!-- 镜内被裁剪的局部特写内容 -->
<g clip-path="url(#zoomClip)">
<!-- 网格参考背景 -->
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱橡胶辊 (横剖面螺旋棱轴向推移) -->
<g transform="translate(560, 68)">
<!-- 辊体 -->
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<!-- 螺旋棱 (螺距 50mm 动态走丝动画) -->
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
<circle cx="-70" cy="0" r="4" fill="#0f172a" />
<circle cx="70" cy="0" r="4" fill="#0f172a" />
</g>
<!-- 特写:下螺旋棱橡胶辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 (向右侧机外排秧) -->
<g transform="translate(560, 95)" opacity="0.9">
<!-- 夹缝标注 -->
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<!-- 轴向横推力流线箭头 -->
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<!-- 下方通过空间示意 -->
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">薯块短圆光滑·畅通滚过 →</text>
</g>
<!-- 局部特写动态层 (镜内的动态秧苗横移与薯块穿过) -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>薯块 (贴链微振 · 穿过辊下间隙)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (被螺旋咬住轴向横推排秧)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>碎土漏回田间</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 46;
const potatoes = [];
const vines = [];
const soilParticles = [];
const collectedPotatoes = [];
const lensElements = [];
// 薯块类:贴紧链面稳定输送,小幅微振,绝不乱飞
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 4;
this.ry = 9 + Math.random() * 3;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 1.5;
this.embedDepth = 452 + Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 地下原状土层推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.85");
this.el.setAttribute("stroke", "#78350f");
} else if (p < 0.30) {
// 铲尖切入与平稳起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 18) * 0.8;
this.el.setAttribute("opacity", "1.0");
this.el.setAttribute("stroke", "#d97706");
} else if (p < 0.55) {
// 一级杆条抖动链:紧贴链面平稳上移,微振 (振幅 ≤1.2px)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 36) * 1.2;
} else if (p < 0.73) {
// 二级杆条筛面平稳输送
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 32) * 1.0;
} else if (p < 0.83) {
// 从对转橡胶辊下方 40mm 间隙安全滚过
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 1.5;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽平滑滑动
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 进入料箱平稳就位
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 复合薯秧体:浮在土薯上方,明显振动上移并被排秧辊咬出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
// 地表植被随土垡被挖掘铲起
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.65) {
// 浮在杆条链上方:显著波浪式振动上移
const t = (p - 0.20) / 0.45;
x = 320 + (745 - 320) * t;
const vibHeight = Math.sin(t * 26) * 4.5 + Math.cos(t * 40) * 2;
const chainY = 425 + (205 - 425) * t;
const liftByComb = t > 0.65 ? (t - 0.65) * 65 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 30) * 8;
} else if (p < 0.85) {
// 被对转螺旋排秧辊咬住向机侧排秧口抛送
const t = (p - 0.65) / 0.20;
x = 745 + (870 - 745) * t;
y = 190 + (90 - 190) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 50;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
// 飞向机侧外
const t = (p - 0.85) / 0.15;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 25;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 24) * 6;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 【新增】特写镜头内动态机理类:清晰展示“秧被咬住横推走”、“薯块从辊下滚过”的特写动作
class LensMechanismDemo {
constructor(type) {
this.type = type; // 'vine' 或 'potato'
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
// 镜内的秧苗
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
// 镜内的薯块
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.005 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
// 秧苗特写:从左侧进入咬缝 (y=95),被螺旋棱咬住后高速向右侧 (机外) 轴向横推运走
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 18) * 1.5;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
// 薯块特写:从左侧 (y=168) 平稳滚过辊下 40mm 间隙,穿行到右侧进入溜槽
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 2;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 360} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 碎土粒子
class SoilParticle {
constructor(x, y, isCuttingBurst = false) {
this.x = x + (Math.random() - 0.5) * (isCuttingBurst ? 12 : 20);
this.y = y + (Math.random() - 0.5) * (isCuttingBurst ? 8 : 10);
this.vx = isCuttingBurst ? (1.5 + Math.random() * 2.0) : ((Math.random() - 0.5) * 1.5);
this.vy = isCuttingBurst ? (-1.5 - Math.random() * 2.0) : (1.2 + Math.random() * 2.5);
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.85");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.14 * timeScale;
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.85));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成薯块
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成茎秆与叶片
if (vineSpawnCounter >= spawnInterval * 1.1) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部放大镜内交替产生“夹秧横移”与“薯块滚过”的特写动作
if (lensSpawnTimer >= 55) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 350);
}
// 铲尖破碎土与筛面漏土
if (Math.random() < 0.65 * timeScale) {
soilParticles.push(new SoilParticle(275 + Math.random() * 25, 465 + Math.random() * 10, true));
}
if (Math.random() < 0.7 * timeScale) {
const t1 = Math.random();
soilParticles.push(new SoilParticle(440 + (600 - 440) * t1, 405 + (315 - 405) * t1 + 8, false));
const t2 = Math.random();
soilParticles.push(new SoilParticle(630 + (760 - 630) * t2, 305 + (230 - 305) * t2 + 8, false));
}
// 更新薯块
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新薯秧茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部放大镜内的特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.06));
potatoes.push(new Potato(0.24));
potatoes.push(new Potato(0.44));
potatoes.push(new Potato(0.66));
potatoes.push(new Potato(0.82));
vines.push(new VineEntity(0.12));
vines.push(new VineEntity(0.38));
vines.push(new VineEntity(0.70));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 2.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 2.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.15s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(4deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 (螺距 50mm 动态平移) */
.main-screw-flow-upper {
animation: mainScrewFlowU 1.4s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 1.4s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 1.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">上下螺旋排秧辊 150mm</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧辊裁剪区域 (用于螺旋走丝) -->
<clipPath id="upperRollerClip">
<rect x="-42" y="-18" width="84" height="36" rx="6"/>
</clipPath>
<clipPath id="lowerRollerClip">
<rect x="-38" y="-14" width="76" height="28" rx="5"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轮 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轮 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条 -->
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="278" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-28 655 278)">二段抖条筛面 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (二段抖条末端上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(740, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转螺旋棱排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱橡胶辊 (直径 150mm,80 r/min 对咬,外显清晰螺旋棱走丝) -->
<g transform="translate(780, 150)">
<!-- 旋转端面指示 -->
<g class="rot-cw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 -12 Q 0 0 18 12" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -12 18 Q 0 0 12 -18" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<!-- 轴向螺旋棱花纹走丝 (立体感螺旋棱动态) -->
<g clip-path="url(#upperRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="3" stroke-linecap="round" opacity="0.9">
<line x1="-55" y1="-18" x2="-35" y2="18" />
<line x1="-35" y1="-18" x2="-15" y2="18" />
<line x1="-15" y1="-18" x2="5" y2="18" />
<line x1="5" y1="-18" x2="25" y2="18" />
<line x1="25" y1="-18" x2="45" y2="18" />
<line x1="45" y1="-18" x2="65" y2="18" />
</g>
</g>
<text x="32" y="-6" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 咬合夹秧导流中缝及轴向推移箭头 -->
<g transform="translate(780, 178)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱橡胶辊 (与上辊形成 40mm 辊间隙,同时下方留出薯块通道) -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="20" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -15 10 Q 0 0 15 -10" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -10 -15 Q 0 0 10 15" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="4.5" fill="#0f172a"/>
</g>
<!-- 下辊反向螺旋棱花纹走丝 -->
<g clip-path="url(#lowerRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.9">
<line x1="-50" y1="14" x2="-30" y2="-14" />
<line x1="-30" y1="14" x2="-10" y2="-14" />
<line x1="-10" y1="14" x2="10" y2="-14" />
<line x1="10" y1="14" x2="30" y2="-14" />
<line x1="30" y1="14" x2="50" y2="-14" />
<line x1="50" y1="14" x2="70" y2="-14" />
</g>
</g>
<text x="28" y="8" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 薯块顺畅滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">箱底 10mm 橡胶减振垫 + 导流板</text>
</g>
<!-- 动态层:土壤漏落、底层薯块托运、表层茎叶抖动上移与排秧 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<!-- 连线引导框 -->
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<!-- 特写圆镜背景与视口 -->
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<!-- 镜内被裁剪的局部特写内容 -->
<g clip-path="url(#zoomClip)">
<!-- 网格参考背景 -->
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱橡胶辊 (横剖面螺旋棱轴向推移) -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
<circle cx="-70" cy="0" r="4" fill="#0f172a" />
<circle cx="70" cy="0" r="4" fill="#0f172a" />
</g>
<!-- 特写:下螺旋棱橡胶辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 (向右侧机外排秧) -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">薯块短圆光滑·畅通滚过 →</text>
</g>
<!-- 局部特写动态层 (镜内的动态秧苗横移与薯块穿过) -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #f59e0b;"></div>
<span>薯块 (穿过二段末端辊下间隙)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #854d0e;"></div>
<span>碎土漏回田间</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 46;
const potatoes = [];
const vines = [];
const soilParticles = [];
const collectedPotatoes = [];
const lensElements = [];
// 薯块类:贴紧链面稳定输送,小幅微振,绝不乱飞
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 4;
this.ry = 9 + Math.random() * 3;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 1.5;
this.embedDepth = 452 + Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 地下原状土层推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.85");
this.el.setAttribute("stroke", "#78350f");
} else if (p < 0.30) {
// 铲尖切入与平稳起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 18) * 0.8;
this.el.setAttribute("opacity", "1.0");
this.el.setAttribute("stroke", "#d97706");
} else if (p < 0.55) {
// 一段杆条抖动链:紧贴链面平稳上移,微振 (振幅 ≤1.2px)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 36) * 1.2;
} else if (p < 0.73) {
// 二段抖条筛面平稳输送
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 32) * 1.0;
} else if (p < 0.83) {
// 在二段抖条末端,从上下对转螺旋橡胶辊下方 40mm 间隙安全滚过
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 1.5;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽平滑滑动
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 进入料箱平稳就位
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 复合薯秧体:浮在土薯上方,明显振动上移,在第二段抖条末端被上下螺旋排秧辊咬入并侧向排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0028 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
// 地表植被随土垡被挖掘铲起
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
// 浮在一、二段杆条链上方:显著波浪式振动上移
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 26) * 4.5 + Math.cos(t * 40) * 2;
const chainY = 425 + (210 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 60 : 0; // 梳齿挑起
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 30) * 8;
} else if (p < 0.86) {
// 在二段抖条末端:被上下对转螺旋排秧辊咬合中缝 (780, 178) 紧紧夹持,沿螺旋推力向机侧排秧口抛出
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 178 + (90 - 178) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 50;
this.stem.setAttribute("stroke", "#86efac"); // 咬住时产生高亮
} else if (p < 1.0) {
// 抛出机外田间
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 25;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 24) * 6;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "#f59e0b");
this.el.setAttribute("stroke", "#b45309");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.005 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 18) * 1.5;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 2;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 360} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 碎土粒子
class SoilParticle {
constructor(x, y, isCuttingBurst = false) {
this.x = x + (Math.random() - 0.5) * (isCuttingBurst ? 12 : 20);
this.y = y + (Math.random() - 0.5) * (isCuttingBurst ? 8 : 10);
this.vx = isCuttingBurst ? (1.5 + Math.random() * 2.0) : ((Math.random() - 0.5) * 1.5);
this.vy = isCuttingBurst ? (-1.5 - Math.random() * 2.0) : (1.2 + Math.random() * 2.5);
this.r = 1.5 + Math.random() * 2.5;
this.life = 1.0;
this.decay = 0.015 + Math.random() * 0.02;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.4 ? "#a16207" : "#78350f");
this.el.setAttribute("opacity", "0.85");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.14 * timeScale;
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.85));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成薯块
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成茎秆与叶片
if (vineSpawnCounter >= spawnInterval * 1.1) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 55) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 350);
}
// 铲尖破碎土与筛面漏土
if (Math.random() < 0.65 * timeScale) {
soilParticles.push(new SoilParticle(275 + Math.random() * 25, 465 + Math.random() * 10, true));
}
if (Math.random() < 0.7 * timeScale) {
const t1 = Math.random();
soilParticles.push(new SoilParticle(440 + (600 - 440) * t1, 405 + (315 - 405) * t1 + 8, false));
const t2 = Math.random();
soilParticles.push(new SoilParticle(630 + (760 - 630) * t2, 305 + (230 - 305) * t2 + 8, false));
}
// 更新薯块
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新薯秧茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.06));
potatoes.push(new Potato(0.24));
potatoes.push(new Potato(0.44));
potatoes.push(new Potato(0.66));
potatoes.push(new Potato(0.82));
vines.push(new VineEntity(0.12));
vines.push(new VineEntity(0.38));
vines.push(new VineEntity(0.70));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 2.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 2.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.14s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.5px, -1px) rotate(0.3deg); }
100% { transform: translate(-1.2px, 1.2px) rotate(-0.3deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.15s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(4deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 (螺距 50mm 动态平移) */
.main-screw-flow-upper {
animation: mainScrewFlowU 1.4s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 1.4s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 1.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">上下螺旋排秧辊 150mm</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧辊裁剪区域 -->
<clipPath id="upperRollerClip">
<rect x="-42" y="-18" width="84" height="36" rx="6"/>
</clipPath>
<clipPath id="lowerRollerClip">
<rect x="-38" y="-14" width="76" height="28" rx="5"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轮 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轮 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条 -->
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="278" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-28 655 278)">二段抖条筛面 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (二段抖条末端上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(740, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转螺旋棱排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱橡胶辊 (直径 150mm,80 r/min 对咬,外显清晰螺旋棱走丝) -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 -12 Q 0 0 18 12" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -12 18 Q 0 0 12 -18" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<g clip-path="url(#upperRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="3" stroke-linecap="round" opacity="0.9">
<line x1="-55" y1="-18" x2="-35" y2="18" />
<line x1="-35" y1="-18" x2="-15" y2="18" />
<line x1="-15" y1="-18" x2="5" y2="18" />
<line x1="5" y1="-18" x2="25" y2="18" />
<line x1="25" y1="-18" x2="45" y2="18" />
<line x1="45" y1="-18" x2="65" y2="18" />
</g>
</g>
<text x="32" y="-6" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 咬合夹秧导流中缝及轴向推移箭头 -->
<g transform="translate(780, 178)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱橡胶辊 (与上辊形成 40mm 辊间隙,同时下方留出薯块通道) -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="20" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -15 10 Q 0 0 15 -10" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -10 -15 Q 0 0 10 15" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="4.5" fill="#0f172a"/>
</g>
<g clip-path="url(#lowerRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.9">
<line x1="-50" y1="14" x2="-30" y2="-14" />
<line x1="-30" y1="14" x2="-10" y2="-14" />
<line x1="-10" y1="14" x2="10" y2="-14" />
<line x1="10" y1="14" x2="30" y2="-14" />
<line x1="30" y1="14" x2="50" y2="-14" />
<line x1="50" y1="14" x2="70" y2="-14" />
</g>
</g>
<text x="28" y="8" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 薯块顺畅滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面微振上移、细土垂直漏落、表层茎叶抖动上移与排秧 -->
<g id="dynamic-soil-particles"></g>
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱橡胶辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
<circle cx="-70" cy="0" r="4" fill="#0f172a" />
<circle cx="70" cy="0" r="4" fill="#0f172a" />
</g>
<!-- 特写:下螺旋棱橡胶辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆光滑·顺畅滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (抖条慢震上移 → 穿过排秧辊 → 掉进集装箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #92400e;"></div>
<span>细碎土壤 (垂直漏回田间)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const soilGroup = document.getElementById('dynamic-soil-particles');
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 46;
const potatoes = [];
const vines = [];
const soilParticles = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:金黄色鲜艳质感,贴紧抖条慢速稳定震动上移,通过螺旋排秧机构后顺畅掉进集装箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 1.2;
this.embedDepth = 452 + Math.random() * 8;
// 创建黄色土豆 SVG 节点
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
// 缓慢而连贯的运送速率
this.progress += dt * 0.0022 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 1. 地下原状土层中稳步推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
// 2. 铲尖切入与平稳起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 16) * 0.6;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 3. 一段杆条抖动链:贴紧抖条慢速震动上移 (微幅受控震颤 ≤1.0px)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 32) * 1.0;
} else if (p < 0.73) {
// 4. 二段抖条筛面:平稳微震上移,输送至排秧区
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 28) * 0.8;
} else if (p < 0.83) {
// 5. 经过螺旋排秧防缠机构:在二段末端从上下螺旋辊下方 40mm 间隙顺畅滚过
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 1.2;
} else if (p < 0.93) {
// 6. 35° 柔性橡胶溜槽平滑滑落
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 7. 顺着导流板安全掉进集装箱,整齐堆叠
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
// 集装箱内静止
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 复合薯秧体:浮在抖条上层明显震动上移,在第二段抖条末端被上下螺旋排秧辊咬入并侧向排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0022 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
// 浮在抖条上方:波浪式震动上移
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 26) * 4.0 + Math.cos(t * 36) * 1.5;
const chainY = 425 + (210 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 60 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 30) * 6;
} else if (p < 0.86) {
// 在二段抖条末端:被上下对转螺旋排秧辊夹持横向抛出
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 178 + (90 - 178) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 50;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 25;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 24) * 5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.004 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 18) * 1.5;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.5;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 360} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细微漏土粒子:柔和土黄色小微粒,平缓垂直自然沉降,绝不乱飞
class SoilParticle {
constructor(x, y) {
this.x = x + (Math.random() - 0.5) * 12;
this.y = y + Math.random() * 4;
this.vx = (Math.random() - 0.5) * 0.4; // 几乎无横向乱飞
this.vy = 1.0 + Math.random() * 1.2; // 温和垂直向下沉降
this.r = 1.0 + Math.random() * 1.5; // 细微颗粒
this.life = 1.0;
this.decay = 0.018 + Math.random() * 0.015;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.el.setAttribute("r", this.r);
this.el.setAttribute("fill", Math.random() > 0.5 ? "#a16207" : "#92400e");
this.el.setAttribute("opacity", "0.7");
soilGroup.appendChild(this.el);
}
update() {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.08 * timeScale; // 平稳重力
this.life -= this.decay * timeScale;
this.el.setAttribute("cx", this.x);
this.el.setAttribute("cy", this.y);
this.el.setAttribute("opacity", Math.max(0, this.life * 0.7));
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成茎秆与叶片
if (vineSpawnCounter >= spawnInterval * 1.2) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 60) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 380);
}
// 抖条筛缝隙平缓垂直自然漏土
if (Math.random() < 0.55 * timeScale) {
const t1 = Math.random();
soilParticles.push(new SoilParticle(450 + (590 - 450) * t1, 410 + (320 - 410) * t1 + 8));
}
if (Math.random() < 0.55 * timeScale) {
const t2 = Math.random();
soilParticles.push(new SoilParticle(640 + (750 - 640) * t2, 310 + (240 - 310) * t2 + 8));
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新薯秧茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
// 更新漏土粒子
for (let i = soilParticles.length - 1; i >= 0; i--) {
const sp = soilParticles[i];
sp.update();
if (sp.life <= 0 || sp.y > 530) {
sp.destroy();
soilParticles.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(20, 56 - density * 9);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.06));
potatoes.push(new Potato(0.24));
potatoes.push(new Potato(0.44));
potatoes.push(new Potato(0.66));
potatoes.push(new Potato(0.82));
vines.push(new VineEntity(0.12));
vines.push(new VineEntity(0.38));
vines.push(new VineEntity(0.70));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 4.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 4.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.2s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1px, -0.6px) rotate(0.2deg); }
100% { transform: translate(-0.8px, 0.8px) rotate(-0.2deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.22s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.5px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.6s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(3.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 2.5s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 2.5s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 2.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">上下螺旋排秧辊 150mm</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<pattern id="soilTexture" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="4" cy="4" r="1.5" fill="#92400e" opacity="0.3"/>
<circle cx="14" cy="12" r="1" fill="#78350f" opacity="0.4"/>
<circle cx="16" cy="6" r="1.2" fill="#451a03" opacity="0.3"/>
</pattern>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧辊裁剪区域 -->
<clipPath id="upperRollerClip">
<rect x="-42" y="-18" width="84" height="36" rx="6"/>
</clipPath>
<clipPath id="lowerRollerClip">
<rect x="-38" y="-14" width="76" height="28" rx="5"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="420" width="270" height="60" fill="url(#soilTexture)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轮 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轮 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条 -->
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="278" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-28 655 278)">二段抖条筛面 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (二段抖条末端上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(740, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转螺旋棱排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱橡胶辊 (直径 150mm,对咬慢速运转,外显清晰螺旋棱走丝) -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 -12 Q 0 0 18 12" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -12 18 Q 0 0 12 -18" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<g clip-path="url(#upperRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="3" stroke-linecap="round" opacity="0.9">
<line x1="-55" y1="-18" x2="-35" y2="18" />
<line x1="-35" y1="-18" x2="-15" y2="18" />
<line x1="-15" y1="-18" x2="5" y2="18" />
<line x1="5" y1="-18" x2="25" y2="18" />
<line x1="25" y1="-18" x2="45" y2="18" />
<line x1="45" y1="-18" x2="65" y2="18" />
</g>
</g>
<text x="32" y="-6" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 咬合夹秧导流中缝及轴向推移箭头 -->
<g transform="translate(780, 178)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱橡胶辊 (与上辊形成 40mm 辊间隙,同时下方留出薯块通道) -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="20" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -15 10 Q 0 0 15 -10" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -10 -15 Q 0 0 10 15" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="4.5" fill="#0f172a"/>
</g>
<g clip-path="url(#lowerRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.9">
<line x1="-50" y1="14" x2="-30" y2="-14" />
<line x1="-30" y1="14" x2="-10" y2="-14" />
<line x1="-10" y1="14" x2="10" y2="-14" />
<line x1="10" y1="14" x2="30" y2="-14" />
<line x1="30" y1="14" x2="50" y2="-14" />
<line x1="50" y1="14" x2="70" y2="-14" />
</g>
</g>
<text x="28" y="8" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面慢速抖动上移、杂草/叶片慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱橡胶辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
<circle cx="-70" cy="0" r="4" fill="#0f172a" />
<circle cx="70" cy="0" r="4" fill="#0f172a" />
</g>
<!-- 特写:下螺旋棱橡胶辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (抖条慢速震动上移 → 穿过排秧辊 → 掉进集装箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (慢速微震上移 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 75; // 提高生成间隔,节奏更从容
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:金黄色质感,贴紧抖条慢速稳定震动上移,通过螺旋排秧机构后顺畅掉进集装箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.4; // 缓慢微转
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
// 慢速平稳运送
this.progress += dt * 0.0009 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
// 1. 地下原状土层中慢速稳步推进
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
// 2. 铲尖切入与平稳起垡抬升
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 3. 一段杆条抖动链:贴紧抖条慢慢震动上移 (温和细微震颤 ≤0.6px)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
// 4. 二段抖条筛面:平稳慢慢微震上移,输送至排秧区
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
// 5. 经过螺旋排秧防缠机构:在二段末端从上下螺旋辊下方 40mm 间隙顺畅慢速滚过
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 6. 35° 柔性橡胶溜槽慢速滑落
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
// 7. 顺着导流板慢慢掉进集装箱,整齐堆叠
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
// 集装箱内静止
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 复合杂草/薯秧体:浮在抖条上层慢慢震动上移,在第二段抖条末端被上下螺旋排秧辊咬入并平缓排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
// 杂草与土豆同频慢速上移
this.progress += dt * 0.0009 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
// 浮在抖条上方:柔和波浪式慢慢震动上移
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (210 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 60 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
// 在二段抖条末端:被上下对转螺旋排秧辊平稳夹持横向抛出
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 178 + (90 - 178) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.0018 * timeScale; // 特写镜内平缓移动
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成杂草与叶片
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 110) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 600);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新杂草茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(40, 95 - density * 12);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 4.5s linear infinite;
}
.rot-ccw {
transform-origin: center;
animation: spin-ccw 4.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes spin-ccw {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
}
.vibrating {
animation: vib 0.2s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1px, -0.6px) rotate(0.2deg); }
100% { transform: translate(-0.8px, 0.8px) rotate(-0.2deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.22s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.5px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.6s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(3.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 2.5s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 2.5s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 2.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">上下螺旋排秧辊 150mm</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<linearGradient id="rollerGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="50%" stop-color="#059669" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<!-- 柔和发光滤镜 -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧辊裁剪区域 -->
<clipPath id="upperRollerClip">
<rect x="-42" y="-18" width="84" height="36" rx="6"/>
</clipPath>
<clipPath id="lowerRollerClip">
<rect x="-38" y="-14" width="76" height="28" rx="5"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (传动系统与杆条) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轮 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轮 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条 -->
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="278" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-28 655 278)">二段抖条筛面 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (二段抖条末端上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(740, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转螺旋棱排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱橡胶辊 (直径 150mm,对咬慢速运转,外显清晰螺旋棱走丝) -->
<g transform="translate(780, 150)">
<g class="rot-cw">
<circle cx="0" cy="0" r="24" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -18 -12 Q 0 0 18 12" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -12 18 Q 0 0 12 -18" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="5" fill="#0f172a"/>
</g>
<g clip-path="url(#upperRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="3" stroke-linecap="round" opacity="0.9">
<line x1="-55" y1="-18" x2="-35" y2="18" />
<line x1="-35" y1="-18" x2="-15" y2="18" />
<line x1="-15" y1="-18" x2="5" y2="18" />
<line x1="5" y1="-18" x2="25" y2="18" />
<line x1="25" y1="-18" x2="45" y2="18" />
<line x1="45" y1="-18" x2="65" y2="18" />
</g>
</g>
<text x="32" y="-6" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 咬合夹秧导流中缝及轴向推移箭头 -->
<g transform="translate(780, 178)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱橡胶辊 (与上辊形成 40mm 辊间隙,同时下方留出薯块通道) -->
<g transform="translate(780, 206)">
<g class="rot-ccw">
<circle cx="0" cy="0" r="20" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2.5"/>
<path d="M -15 10 Q 0 0 15 -10" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<path d="M -10 -15 Q 0 0 10 15" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" fill="none"/>
<circle cx="0" cy="0" r="4.5" fill="#0f172a"/>
</g>
<g clip-path="url(#lowerRollerClip)" transform="translate(0, 0)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.9">
<line x1="-50" y1="14" x2="-30" y2="-14" />
<line x1="-30" y1="14" x2="-10" y2="-14" />
<line x1="-10" y1="14" x2="10" y2="-14" />
<line x1="10" y1="14" x2="30" y2="-14" />
<line x1="30" y1="14" x2="50" y2="-14" />
<line x1="50" y1="14" x2="70" y2="-14" />
</g>
</g>
<text x="28" y="8" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面慢速抖动上移、杂草/叶片慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱橡胶辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
<circle cx="-70" cy="0" r="4" fill="#0f172a" />
<circle cx="70" cy="0" r="4" fill="#0f172a" />
</g>
<!-- 特写:下螺旋棱橡胶辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#rollerGrad)" stroke="#22c55e" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (抖条慢速震动上移 → 穿过排秧辊 → 掉进集装箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (慢速微震上移 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 75;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:金黄色质感,贴紧抖条慢速稳定震动上移,通过螺旋排秧机构后顺畅掉进集装箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.4;
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 复合杂草/薯秧体:浮在抖条上层慢慢震动上移,在第二段抖条末端被上下螺旋排秧辊咬入并平缓排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.8");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.leaf1 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf1.setAttribute("rx", "7");
this.leaf1.setAttribute("ry", "3.8");
this.leaf1.setAttribute("fill", "#22c55e");
this.group.appendChild(this.leaf1);
this.leaf2 = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.leaf2.setAttribute("rx", "6");
this.leaf2.setAttribute("ry", "3.2");
this.leaf2.setAttribute("fill", "#4ade80");
this.group.appendChild(this.leaf2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (210 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 60 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 178 + (90 - 178) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const l1x = x - dx * 0.3;
const l1y = y - dy * 0.3 - 3;
this.leaf1.setAttribute("cx", l1x);
this.leaf1.setAttribute("cy", l1y);
this.leaf1.setAttribute("transform", `rotate(${stemAngle - 25} ${l1x} ${l1y})`);
const l2x = x + dx * 0.4;
const l2y = y + dy * 0.4 + 2;
this.leaf2.setAttribute("cx", l2x);
this.leaf2.setAttribute("cy", l2y);
this.leaf2.setAttribute("transform", `rotate(${stemAngle + 35} ${l2x} ${l2y})`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.0018 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成杂草与叶片
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 110) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 600);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新杂草茎叶
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(40, 95 - density * 12);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 4.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.2s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1px, -0.6px) rotate(0.2deg); }
100% { transform: translate(-0.8px, 0.8px) rotate(-0.2deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.22s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.5px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.6s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(3.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 (圆柱形辊体内部) */
.main-screw-flow-upper {
animation: mainScrewFlowU 2.5s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 2.5s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 2.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">上下螺旋排秧辊 150mm</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轴 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轴 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="225" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条 -->
<path d="M 630 305 L 780 225" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 240" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="282" x2="670" y2="297" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="255" x2="720" y2="270" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="278" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-28 655 278)">二段抖条筛面 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (二段抖条末端上前方挑起长秧) -->
<g id="comb-curtain" transform="translate(740, 140)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转机械圆柱螺旋排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (指向机侧与后方) -->
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 155 Q 835 110 885 90" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="80" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 (标准机械圆柱体构型) -->
<g transform="translate(780, 150)">
<!-- 机械支架与轴承端盖 -->
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<!-- 圆柱体内动态螺旋棱走丝 -->
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 咬合夹秧导流中缝及轴向推移箭头 -->
<g transform="translate(780, 178)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 (间隙 40mm,下方留出土豆通道) -->
<g transform="translate(780, 206)">
<!-- 机械圆柱辊体 -->
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<!-- 下辊反向螺旋棱走丝 -->
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="240" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="254" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 240)">
<path d="M 0 0 L 75 60 L 90 115" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 57 L 87 112" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="40" y="30" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="40" y="44" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面慢速抖动上移、杂草/茎蔓慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 178 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 240 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (抖条慢速震动上移 → 穿过排秧辊 → 掉进集装箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (慢速微震上移 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 75;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:金黄色质感,贴紧抖条慢速稳定震动上移,通过螺旋排秧机构后顺畅掉进集装箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.4;
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (235 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 238 + (245 - 238) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 245 + (335 - 245) * (t * t);
} else if (p < 1.0) {
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 335 + (460 - 335) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:纯细长线条构型,彻底移除球状物,慢速抖动上移并被螺旋排秧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
// 主茎藤蔓
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
// 细长分叉嫩须 1 (细线条,非圆球)
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
// 细长分叉嫩须 2 (细线条,非圆球)
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (210 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 60 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 178 + (90 - 178) * Math.sin(t * (Math.PI / 2));
stemAngle = -40 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 90 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
// 绘制纤细嫩须分叉线条
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.0018 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 110) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 600);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(40, 95 - density * 12);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 4.5s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.2s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1px, -0.6px) rotate(0.2deg); }
100% { transform: translate(-0.8px, 0.8px) rotate(-0.2deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.22s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.5px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.6s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(3.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 2.5s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 2.5s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 2.2s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">二段抖条末端正对上下螺旋中缝</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条末端正对上下两螺旋辊中间,y从225移至245) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轴 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轴:末端定在 (780, 245) 正对两辊之间 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="245" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条:斜面平稳延伸至两螺旋中缝 (780, 245) -->
<path d="M 630 305 L 780 245" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 260" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="288" x2="670" y2="303" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="268" x2="720" y2="283" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="292" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-22 655 292)">二段抖条末端正对两辊中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (下移至合适挑秧高度) -->
<g id="comb-curtain" transform="translate(740, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:两个螺旋排秧整体向下移动 (上辊y=190, 下辊y=265, 中缝y=228~245),二段抖条末端精准位于两辊中间 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (从下移后的辊位引向排秧口) -->
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="105" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 (向下移至 y=190) -->
<g transform="translate(780, 190)">
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 两辊咬合夹秧中缝流线 (向下移至 y=228) -->
<g transform="translate(780, 228)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 (向下移至 y=265) -->
<g transform="translate(780, 265)">
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 (向下移至 y=298) -->
<rect x="740" y="295" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="309" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 (衔接下移后的排秧末端,起点下移至 y=295) -->
<g id="buffer-chute" transform="translate(850, 295)">
<path d="M 0 0 L 75 40 L 90 75" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 37 L 87 72" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="35" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="35" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面慢速抖动上移、杂草/茎蔓慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 228 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 295 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (二段末端正对两螺旋中缝 → 辊下滚过 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 75;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:金黄色质感,在二段抖条末端正对两螺旋中间平稳到达,穿过辊下间隙后顺畅滑落进箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.4;
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 3. 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
// 4. 二段抖条斜面:斜面平稳延伸到达两个螺旋中间 (620, 315) -> (780, 245)
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (245 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
// 5. 经过两螺旋中间后顺畅从下辊下方间隙滚过进入溜槽 (780, 245) -> (850, 295)
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 245 + (295 - 245) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 6. 35° 柔性橡胶溜槽滑落 (850, 295) -> (935, 355)
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 295 + (355 - 295) * (t * t);
} else if (p < 1.0) {
// 7. 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:在二段抖条末端(两螺旋中间)被上下两辊对转咬合中缝夹住并抛向机侧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.0009 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (228 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
// 在二段末端正对两螺旋中间 (y=228) 咬入并沿螺旋推力斜向抛向排秧口
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 228 + (115 - 228) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 115 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.0018 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 110) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 600);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(40, 95 - density * 12);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.35s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(0.8px, -0.4px) rotate(0.15deg); }
100% { transform: translate(-0.6px, 0.6px) rotate(-0.15deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.4s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 1.2s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">二段抖条末端正对上下螺旋中缝</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="#1e293b" stroke="#38bdf8" stroke-width="4"/>
<circle cx="0" cy="0" r="32" fill="#0f172a" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="8" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<circle cx="0" cy="0" r="14" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<circle cx="4" cy="-4" r="5" fill="#f59e0b"/>
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条末端正对两螺旋中间) -->
<g id="conveyor-system">
<g id="rollers" stroke="#475569" stroke-width="4">
<!-- 一段抖条两端转轴 -->
<circle cx="440" cy="405" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="600" cy="315" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<!-- 二段抖条两端转轴:末端在 (780, 245) 正对两辊之间 -->
<circle cx="630" cy="305" r="14" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
<circle cx="780" cy="245" r="16" fill="#1e293b" stroke="#38bdf8" stroke-width="3" class="rot-cw"/>
</g>
<!-- 链条支架与输送杆条排 -->
<g class="chain-vibrating">
<!-- 一段抖条 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#1e293b" stroke-width="3"/>
<!-- 二段抖条:斜面平稳延伸至两螺旋中缝 (780, 245) -->
<path d="M 630 305 L 780 245" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 260" stroke="#1e293b" stroke-width="3"/>
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="288" x2="670" y2="303" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="268" x2="720" y2="283" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="292" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-22 655 292)">二段抖条末端正对两辊中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(740, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转机械圆柱螺旋排秧辊机构 (上辊y=190, 下辊y=265, 中间y=228~245) -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="105" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 -->
<g transform="translate(780, 190)">
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 两辊咬合夹秧中缝流线 -->
<g transform="translate(780, 228)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 -->
<g transform="translate(780, 265)">
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="295" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="309" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 295)">
<path d="M 0 0 L 75 40 L 90 75" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 37 L 87 72" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="35" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="35" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 228 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 295 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (超慢速抖动上移 → 穿过排秧辊 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (超慢速微震上移 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375; // 慢5倍后生成间隔同步扩大5倍,保持间距匀称
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:慢速5倍(0.00018),在二段抖条末端正对两螺旋中间平稳到达,穿过辊下间隙后顺畅滑落进箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08; // 旋转速率慢5倍
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
// 慢5倍的平稳运送速度:0.0009 / 5 = 0.00018
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
// 二段抖条斜面:斜面平稳延伸到达两个螺旋中间 (620, 315) -> (780, 245)
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (245 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
// 经过两螺旋中间后顺畅从下辊下方间隙滚过进入溜槽 (780, 245) -> (850, 295)
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 245 + (295 - 245) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (850, 295) -> (935, 355)
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 295 + (355 - 295) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:慢速5倍(0.00018),在二段末端正对两螺旋中间被咬住平缓排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
// 杂草速度同步慢5倍:0.0009 / 5 = 0.00018
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (228 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 228 + (115 - 228) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 115 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类:同步慢5倍(0.00036)
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
// 特写镜速度同步慢5倍:0.0018 / 5 = 0.00036
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.35s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(0.8px, -0.4px) rotate(0.15deg); }
100% { transform: translate(-0.6px, 0.6px) rotate(-0.15deg); }
}
/* 杆条振动微动特效 */
.chain-vibrating {
animation: chain-vib 0.4s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.2px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 1.2s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">二段抖条末端正对上下螺旋中缝</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 (纯金属框架构型,无黑球) -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 (纯流线金属铲体,无黑球) -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (彻底移除所有黑色圆球/黑轮,采用极简纯净导轨与杆条排) -->
<g id="conveyor-system">
<!-- 纯净链条支架与输送杆条排 (已删除中间及两端的所有黑球) -->
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 (无黑球) -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面平稳延伸至两螺旋中缝 (780, 245) -->
<path d="M 630 305 L 780 245" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 260" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="288" x2="670" y2="303" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="268" x2="720" y2="283" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="292" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-22 655 292)">二段抖条末端正对两辊中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(740, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转机械圆柱螺旋排秧辊机构 (无任何黑球) -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="105" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 -->
<g transform="translate(780, 190)">
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 两辊咬合夹秧中缝流线 -->
<g transform="translate(780, 228)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 -->
<g transform="translate(780, 265)">
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="295" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="309" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 295)">
<path d="M 0 0 L 75 40 L 90 75" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 37 L 87 72" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="35" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="35" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 228 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 295 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (超慢速抖动上移 → 穿过排秧辊 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (超慢速微震上移 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 黄色土豆类:慢速5倍(0.00018),在二段抖条末端正对两螺旋中间平稳到达,穿过辊下间隙后顺畅滑落进箱
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + Math.sin(t * 14) * 0.4;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 26) * 0.6;
} else if (p < 0.73) {
// 二段抖条斜面:斜面平稳延伸到达两个螺旋中间 (620, 315) -> (780, 245)
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (245 - 315) * t;
y = chainLineY - this.ry * 0.9 + Math.sin(t * 22) * 0.5;
} else if (p < 0.83) {
// 经过两螺旋中间后顺畅从下辊下方间隙滚过进入溜槽 (780, 245) -> (850, 295)
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 245 + (295 - 245) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (850, 295) -> (935, 355)
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 295 + (355 - 295) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:慢速5倍(0.00018),在二段末端正对两螺旋中间被咬住平缓排出
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const vibHeight = Math.sin(t * 18) * 2.5 + Math.cos(t * 26) * 1.0;
const chainY = 425 + (228 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + vibHeight;
stemAngle = -15 - t * 25 + Math.sin(t * 20) * 4;
} else if (p < 0.86) {
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 228 + (115 - 228) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 115 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(this.progress * 18) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类:同步慢5倍(0.00036)
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(p * 12) * 1.0;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.12s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(0.8px, -0.4px) rotate(0.15deg); }
100% { transform: translate(-0.6px, 0.6px) rotate(-0.15deg); }
}
/* 杆条振动微动特效(速度提高3倍:0.4s -> 0.133s) */
.chain-vibrating {
animation: chain-vib 0.133s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.4px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">抖动频率: <span class="val" id="val-freq">7.5 Hz (高速微振)</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (高速抖动) -->
<g id="conveyor-system">
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面平稳延伸至两螺旋中缝 (780, 245) -->
<path d="M 630 305 L 780 245" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 780 260" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="670" y1="288" x2="670" y2="303" stroke="#38bdf8" stroke-width="2"/>
<line x1="720" y1="268" x2="720" y2="283" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="655" y="292" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-22 655 292)">二段抖条末端正对两辊中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(740, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:二段抖条末端上下对转机械圆柱螺旋排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 780 195 Q 835 145 885 115" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="835" y="105" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 -->
<g transform="translate(780, 190)">
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 两辊咬合夹秧中缝流线 -->
<g transform="translate(780, 228)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 -->
<g transform="translate(780, 265)">
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 -->
<rect x="740" y="295" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="746" y="309" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(850, 295)">
<path d="M 0 0 L 75 40 L 90 75" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 72 37 L 87 72" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="35" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="35" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 760 228 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 780 295 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (超慢速运移 + 3倍速高频微抖 → 穿过排秧辊 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (超慢速运移 + 高频微抖 → 二段末端螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 高频抖动相位累加器(快3倍抖动专用)
let vibePhase = 0;
// 黄色土豆类:慢速5倍平移,抖动频率提高3倍
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.phaseSeed = Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
// 3倍快速抖动分量(高频微幅)
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 0.8;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + fastVibe * 0.6;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315) - 快3倍高频微抖
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + fastVibe;
} else if (p < 0.73) {
// 二段抖条斜面 (620, 315) -> (780, 245) - 快3倍高频微抖
const t = (p - 0.55) / 0.18;
x = 620 + (780 - 620) * t;
const chainLineY = 315 + (245 - 315) * t;
y = chainLineY - this.ry * 0.9 + fastVibe * 0.85;
} else if (p < 0.83) {
// 经过两螺旋中间后顺畅从下辊下方间隙滚过进入溜槽 (780, 245) -> (850, 295)
const t = (p - 0.73) / 0.10;
x = 780 + (850 - 780) * t;
y = 245 + (295 - 245) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (850, 295) -> (935, 355)
const t = (p - 0.83) / 0.10;
x = 850 + (935 - 850) * t;
y = 295 + (355 - 295) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:慢速5倍平移,抖动频率提高3倍
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.phaseSeed = Math.random() * 10;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
// 3倍快速抖动分量
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 2.8 + Math.cos(vibePhase * 4.5) * 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.70) {
const t = (p - 0.20) / 0.50;
x = 320 + (760 - 320) * t;
const chainY = 425 + (228 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + fastVibe;
stemAngle = -15 - t * 25 + Math.sin(vibePhase * 2.5) * 5;
} else if (p < 0.86) {
const t = (p - 0.70) / 0.16;
x = 760 + (870 - 760) * t;
y = 228 + (115 - 228) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 870 + 60 * t;
y = 115 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(vibePhase * 2.0 + this.phaseSeed) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(vibePhase * 2.0) * 1.2;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
// 抖动频率累加(提高3倍)
vibePhase += dt * 0.015 * timeScale;
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.12s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(0.8px, -0.4px) rotate(0.15deg); }
100% { transform: translate(-0.6px, 0.6px) rotate(-0.15deg); }
}
/* 杆条振动微动特效(速度保持3倍快振) */
.chain-vibrating {
animation: chain-vib 0.133s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.4px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">二段筛末端: <span class="val">二段抖条末端正对上下螺旋中缝</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-14" width="80" height="28" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-12" width="72" height="24" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条延伸至右移后的末端 800, 240) -->
<g id="conveyor-system">
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面延伸至两螺旋中缝前端 (800, 240) -->
<path d="M 630 305 L 800 240" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 800 255" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="675" y1="288" x2="675" y2="303" stroke="#38bdf8" stroke-width="2"/>
<line x1="735" y1="265" x2="735" y2="280" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="665" y="292" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-21 665 292)">二段抖条末端正对两辊中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 (向右微调至 x=760) -->
<g id="comb-curtain" transform="translate(760, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="58" />
<line x1="9" y1="0" x2="13" y2="56" />
<line x1="15" y1="0" x2="20" y2="60" />
<line x1="21" y1="0" x2="27" y2="54" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:两个螺旋向右边移动(从 x=780 右移至 x=815),位于二段抖条末端 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (起点右移至 815, 195) -->
<path d="M 815 195 Q 860 145 905 115" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 815 195 Q 860 145 905 115" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="855" y="105" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 (右移至 x=815, y=190) -->
<g transform="translate(815, 190)">
<rect x="-42" y="-15" width="84" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-14" x2="-35" y2="14" />
<line x1="-35" y1="-14" x2="-15" y2="14" />
<line x1="-15" y1="-14" x2="5" y2="14" />
<line x1="5" y1="-14" x2="25" y2="14" />
<line x1="25" y1="-14" x2="45" y2="14" />
<line x1="45" y1="-14" x2="65" y2="14" />
</g>
</g>
<text x="46" y="-5" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 两辊咬合夹秧中缝流线 (右移至 x=815, y=228) -->
<g transform="translate(815, 228)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 (右移至 x=815, y=265) -->
<g transform="translate(815, 265)">
<rect x="-38" y="-13" width="76" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="12" x2="-30" y2="-12" />
<line x1="-30" y1="12" x2="-10" y2="-12" />
<line x1="-10" y1="12" x2="10" y2="-12" />
<line x1="10" y1="12" x2="30" y2="-12" />
<line x1="30" y1="12" x2="50" y2="-12" />
<line x1="50" y1="12" x2="70" y2="-12" />
</g>
</g>
<text x="42" y="7" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (间隙 40mm)</text>
</g>
<!-- 导流通道标注 (右移至 x=775, y=295) -->
<rect x="775" y="295" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="781" y="309" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 (衔接右移后的排秧末端,起点在 870, 295) -->
<g id="buffer-chute" transform="translate(870, 295)">
<path d="M 0 0 L 55 35 L 70 70" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 52 32 L 67 67" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="25" y="20" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="25" y="34" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (对转螺旋排秧与空间分流机理特写) -->
<g id="detail-zoom-lens">
<path d="M 790 228 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 815 295 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:上螺旋棱机械圆柱辊 -->
<g transform="translate(560, 68)">
<rect x="-70" y="-18" width="140" height="36" rx="6" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-18" x2="-62" y2="18" />
<line x1="-56" y1="-18" x2="-38" y2="18" />
<line x1="-32" y1="-18" x2="-14" y2="18" />
<line x1="-8" y1="-18" x2="10" y2="18" />
<line x1="16" y1="-18" x2="34" y2="18" />
<line x1="40" y1="-18" x2="58" y2="18" />
<line x1="64" y1="-18" x2="82" y2="18" />
</g>
</g>
<!-- 特写:下螺旋棱机械圆柱辊 -->
<g transform="translate(560, 122)">
<rect x="-70" y="-14" width="140" height="28" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="14" x2="-62" y2="-14" />
<line x1="-56" y1="14" x2="-38" y2="-14" />
<line x1="-32" y1="14" x2="-14" y2="-14" />
<line x1="-8" y1="14" x2="10" y2="-14" />
<line x1="16" y1="14" x2="34" y2="-14" />
<line x1="40" y1="14" x2="58" y2="-14" />
<line x1="64" y1="14" x2="82" y2="-14" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下 40mm 间隙薯块通道 -->
<g transform="translate(560, 168)">
<rect x="-75" y="-18" width="150" height="36" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-4" fill="#38bdf8" font-size="8.5">40mm 辊下间隙</text>
<text x="-65" y="8" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (二段末端螺旋排秧 → 辊下滚过 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 高频抖动相位累加器(快3倍抖动)
let vibePhase = 0;
// 黄色土豆类:慢速5倍平移,二段抖条延伸并正对右移后的两螺旋 (815, 228~240) 中间
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.phaseSeed = Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 0.8;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + fastVibe * 0.6;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + fastVibe;
} else if (p < 0.74) {
// 二段抖条斜面延伸至右移后的两螺旋末端 (620, 315) -> (815, 238)
const t = (p - 0.55) / 0.19;
x = 620 + (815 - 620) * t;
const chainLineY = 315 + (238 - 315) * t;
y = chainLineY - this.ry * 0.9 + fastVibe * 0.85;
} else if (p < 0.84) {
// 在二段末端顺畅从下辊下方间隙滚过进入溜槽 (815, 238) -> (870, 295)
const t = (p - 0.74) / 0.10;
x = 815 + (870 - 815) * t;
y = 238 + (295 - 238) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (870, 295) -> (935, 355)
const t = (p - 0.84) / 0.09;
x = 870 + (935 - 870) * t;
y = 295 + (355 - 295) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:在二段末端右移后的两螺旋 (815, 228) 处被对转咬合排向机侧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.phaseSeed = Math.random() * 10;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 2.8 + Math.cos(vibePhase * 4.5) * 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.72) {
const t = (p - 0.20) / 0.52;
x = 320 + (800 - 320) * t;
const chainY = 425 + (228 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + fastVibe;
stemAngle = -15 - t * 25 + Math.sin(vibePhase * 2.5) * 5;
} else if (p < 0.86) {
// 在二段末端右移后的螺旋中缝 (815, 228) 咬入并抛向排秧口
const t = (p - 0.72) / 0.14;
x = 800 + (900 - 800) * t;
y = 228 + (115 - 228) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 900 + 55 * t;
y = 115 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(vibePhase * 2.0 + this.phaseSeed) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(vibePhase * 2.0) * 1.2;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 168 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
vibePhase += dt * 0.015 * timeScale;
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.vibrating {
animation: vib 0.12s linear infinite alternate;
}
@keyframes vib {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(0.8px, -0.4px) rotate(0.15deg); }
100% { transform: translate(-0.6px, 0.6px) rotate(-0.15deg); }
}
/* 杆条振动微动特效(3倍快振) */
.chain-vibrating {
animation: chain-vib 0.133s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.4px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm</span></div>
<div class="badge">螺旋间隙: <span class="val">紧凑夹持窄缝</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 (紧凑型) -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-13" width="80" height="26" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-11" width="72" height="22" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 -->
<g id="vibrating-blade-group" class="vibrating">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2" stroke-dasharray="3 3"/>
</g>
<text x="270" y="515" fill="#38bdf8" font-size="10">20°入土角·温和起垡振动铲</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条延伸至紧凑两螺旋中间 800, 230) -->
<g id="conveyor-system">
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面平稳延伸至紧凑两螺旋中缝前端 (800, 230) -->
<path d="M 630 305 L 800 230" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 800 245" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="675" y1="285" x2="675" y2="300" stroke="#38bdf8" stroke-width="2"/>
<line x1="735" y1="258" x2="735" y2="273" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="665" y="285" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-23 665 285)">二段抖条末端正对紧凑螺旋中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(760, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="52" />
<line x1="9" y1="0" x2="13" y2="50" />
<line x1="15" y1="0" x2="20" y2="54" />
<line x1="21" y1="0" x2="27" y2="48" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:两个螺旋排秧辊间距收窄(上辊 y=210, 下辊 y=250,咬合中缝 y=230,紧凑窄缝) -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 (从紧凑辊缝引向排秧口) -->
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="855" y="115" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 (下调至 y=210,收窄上下间距) -->
<g transform="translate(815, 210)">
<rect x="-42" y="-13" width="84" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-13" x2="-35" y2="13" />
<line x1="-35" y1="-13" x2="-15" y2="13" />
<line x1="-15" y1="-13" x2="5" y2="13" />
<line x1="5" y1="-13" x2="25" y2="13" />
<line x1="25" y1="-13" x2="45" y2="13" />
<line x1="45" y1="-13" x2="65" y2="13" />
</g>
</g>
<text x="46" y="-4" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 紧凑咬合夹秧中缝流线 (y=230) -->
<g transform="translate(815, 230)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 (上调至 y=250,间距明显收窄) -->
<g transform="translate(815, 250)">
<rect x="-38" y="-11" width="76" height="22" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="11" x2="-30" y2="-11" />
<line x1="-30" y1="11" x2="-10" y2="-11" />
<line x1="-10" y1="11" x2="10" y2="-11" />
<line x1="10" y1="11" x2="30" y2="-11" />
<line x1="30" y1="11" x2="50" y2="-11" />
<line x1="50" y1="11" x2="70" y2="-11" />
</g>
</g>
<text x="42" y="5" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (紧凑窄缝)</text>
</g>
<!-- 导流通道标注 (y=278) -->
<rect x="775" y="278" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="781" y="292" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 (衔接收窄后的排秧末端,起点在 865, 278) -->
<g id="buffer-chute" transform="translate(865, 278)">
<path d="M 0 0 L 60 40 L 75 80" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 57 37 L 72 77" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="25" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="25" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 (紧凑窄缝特写) -->
<g id="detail-zoom-lens">
<path d="M 790 230 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 815 278 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:紧凑上螺旋辊 (y=75) -->
<g transform="translate(560, 75)">
<rect x="-70" y="-15" width="140" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-15" x2="-62" y2="15" />
<line x1="-56" y1="-15" x2="-38" y2="15" />
<line x1="-32" y1="-15" x2="-14" y2="15" />
<line x1="-8" y1="-15" x2="10" y2="15" />
<line x1="16" y1="-15" x2="34" y2="15" />
<line x1="40" y1="-15" x2="58" y2="15" />
<line x1="64" y1="-15" x2="82" y2="15" />
</g>
</g>
<!-- 特写:紧凑下螺旋辊 (y=115) -->
<g transform="translate(560, 115)">
<rect x="-70" y="-12" width="140" height="24" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="12" x2="-62" y2="-12" />
<line x1="-56" y1="12" x2="-38" y2="-12" />
<line x1="-32" y1="12" x2="-14" y2="-12" />
<line x1="-8" y1="12" x2="10" y2="-12" />
<line x1="16" y1="12" x2="34" y2="-12" />
<line x1="40" y1="12" x2="58" y2="-12" />
<line x1="64" y1="12" x2="82" y2="-12" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 (紧凑中缝 y=95) -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">紧凑夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下间隙薯块通道 (y=160) -->
<g transform="translate(560, 160)">
<rect x="-75" y="-16" width="150" height="32" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-3" fill="#38bdf8" font-size="8.5">辊下通过间隙</text>
<text x="-65" y="9" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (二段末端紧凑螺旋排秧 → 辊下滚过 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 高频抖动相位累加器(3倍快抖)
let vibePhase = 0;
// 黄色土豆类:慢速5倍平移,二段抖条延伸并正对紧凑两螺旋 (815, 230) 中间
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.phaseSeed = Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 0.8;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + fastVibe * 0.6;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + fastVibe;
} else if (p < 0.74) {
// 二段抖条斜面延伸至紧凑两螺旋末端 (620, 315) -> (815, 230)
const t = (p - 0.55) / 0.19;
x = 620 + (815 - 620) * t;
const chainLineY = 315 + (230 - 315) * t;
y = chainLineY - this.ry * 0.9 + fastVibe * 0.85;
} else if (p < 0.84) {
// 在二段末端顺畅从紧凑下辊下方间隙滚过进入溜槽 (815, 230) -> (865, 278)
const t = (p - 0.74) / 0.10;
x = 815 + (865 - 815) * t;
y = 230 + (278 - 230) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (865, 278) -> (935, 355)
const t = (p - 0.84) / 0.09;
x = 865 + (935 - 865) * t;
y = 278 + (355 - 278) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:在二段末端紧凑两螺旋 (815, 230) 处被对转咬合排向机侧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.phaseSeed = Math.random() * 10;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 2.8 + Math.cos(vibePhase * 4.5) * 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.72) {
const t = (p - 0.20) / 0.52;
x = 320 + (800 - 320) * t;
const chainY = 425 + (230 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + fastVibe;
stemAngle = -15 - t * 25 + Math.sin(vibePhase * 2.5) * 5;
} else if (p < 0.86) {
// 在二段末端紧凑螺旋中缝 (815, 230) 咬入并抛向排秧口
const t = (p - 0.72) / 0.14;
x = 800 + (900 - 800) * t;
y = 230 + (125 - 230) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 900 + 55 * t;
y = 125 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(vibePhase * 2.0 + this.phaseSeed) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类 (紧凑中缝)
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(vibePhase * 2.0) * 1.2;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 160 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
vibePhase += dt * 0.015 * timeScale;
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* 挖掘铲高频强力振动特效(加快四倍:0.12s -> 0.03s) */
.vibrating-blade-fast {
animation: vib-blade 0.03s linear infinite alternate;
}
@keyframes vib-blade {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.4px, -0.9px) rotate(0.35deg); }
100% { transform: translate(-1.2px, 1.1px) rotate(-0.35deg); }
}
/* 杆条振动微动特效(3倍快振) */
.chain-vibrating {
animation: chain-vib 0.133s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.4px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm (限深轮定深)</span></div>
<div class="badge">铲刃震频: <span class="val" id="val-blade-freq">32 Hz (4倍高频强震)</span></div>
<div class="badge">排秧转速: <span class="val" id="val-rpm">80 r/min</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-13" width="80" height="26" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-11" width="72" height="22" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 (锁定入土深度 15cm) -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定铲刃入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 (震动速度加快四倍:vibrating-blade-fast) -->
<g id="vibrating-blade-group" class="vibrating-blade-fast">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2.5" stroke-dasharray="2 2"/>
</g>
<text x="260" y="515" fill="#38bdf8" font-size="10" font-weight="bold">20°入土角·振动挖掘铲 (4倍高频强震)</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条延伸至紧凑两螺旋中间 800, 230) -->
<g id="conveyor-system">
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面平稳延伸至紧凑两螺旋中缝前端 (800, 230) -->
<path d="M 630 305 L 800 230" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 800 245" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="675" y1="285" x2="675" y2="300" stroke="#38bdf8" stroke-width="2"/>
<line x1="735" y1="258" x2="735" y2="273" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="665" y="285" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-23 665 285)">二段抖条末端正对紧凑螺旋中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(760, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="52" />
<line x1="9" y1="0" x2="13" y2="50" />
<line x1="15" y1="0" x2="20" y2="54" />
<line x1="21" y1="0" x2="27" y2="48" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:两个螺旋排秧辊间距收窄(上辊 y=210, 下辊 y=250,咬合中缝 y=230,紧凑窄缝) -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="855" y="115" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 -->
<g transform="translate(815, 210)">
<rect x="-42" y="-13" width="84" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-13" x2="-35" y2="13" />
<line x1="-35" y1="-13" x2="-15" y2="13" />
<line x1="-15" y1="-13" x2="5" y2="13" />
<line x1="5" y1="-13" x2="25" y2="13" />
<line x1="25" y1="-13" x2="45" y2="13" />
<line x1="45" y1="-13" x2="65" y2="13" />
</g>
</g>
<text x="46" y="-4" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 紧凑咬合夹秧中缝流线 -->
<g transform="translate(815, 230)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 -->
<g transform="translate(815, 250)">
<rect x="-38" y="-11" width="76" height="22" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="11" x2="-30" y2="-11" />
<line x1="-30" y1="11" x2="-10" y2="-11" />
<line x1="-10" y1="11" x2="10" y2="-11" />
<line x1="10" y1="11" x2="30" y2="-11" />
<line x1="30" y1="11" x2="50" y2="-11" />
<line x1="50" y1="11" x2="70" y2="-11" />
</g>
</g>
<text x="42" y="5" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (紧凑窄缝)</text>
</g>
<!-- 导流通道标注 -->
<rect x="775" y="278" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="781" y="292" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(865, 278)">
<path d="M 0 0 L 60 40 L 75 80" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 57 37 L 72 77" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="25" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="25" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面超慢速抖动上移、杂草/茎蔓超慢速震动上移与排秧 -->
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 -->
<g id="detail-zoom-lens">
<path d="M 790 230 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 815 278 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:紧凑上螺旋辊 -->
<g transform="translate(560, 75)">
<rect x="-70" y="-15" width="140" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-15" x2="-62" y2="15" />
<line x1="-56" y1="-15" x2="-38" y2="15" />
<line x1="-32" y1="-15" x2="-14" y2="15" />
<line x1="-8" y1="-15" x2="10" y2="15" />
<line x1="16" y1="-15" x2="34" y2="15" />
<line x1="40" y1="-15" x2="58" y2="15" />
<line x1="64" y1="-15" x2="82" y2="15" />
</g>
</g>
<!-- 特写:紧凑下螺旋辊 -->
<g transform="translate(560, 115)">
<rect x="-70" y="-12" width="140" height="24" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="12" x2="-62" y2="-12" />
<line x1="-56" y1="12" x2="-38" y2="-12" />
<line x1="-32" y1="12" x2="-14" y2="-12" />
<line x1="-8" y1="12" x2="10" y2="-12" />
<line x1="16" y1="12" x2="34" y2="-12" />
<line x1="40" y1="12" x2="58" y2="-12" />
<line x1="64" y1="12" x2="82" y2="-12" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">紧凑夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下间隙薯块通道 -->
<g transform="translate(560, 160)">
<rect x="-75" y="-16" width="150" height="32" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-3" fill="#38bdf8" font-size="8.5">辊下通过间隙</text>
<text x="-65" y="9" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡 (4倍高频强震) 与筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (二段末端紧凑螺旋排秧 → 辊下滚过 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const collectedPotatoes = [];
const lensElements = [];
// 高频抖动相位累加器(快3倍抖动)
let vibePhase = 0;
// 挖掘铲4倍高频振动相位累加器
let bladeVibePhase = 0;
// 黄色土豆类:慢速5倍平移,在振动挖掘铲处受到4倍高频强震碎土抬起
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.phaseSeed = Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 0.8;
// 铲体4倍高频微震
const bladeFastVibe = Math.sin(bladeVibePhase * 4.0 + this.phaseSeed) * 1.2;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
// 挖掘铲切土抬升阶段:受限深轮定深并在4倍高频强震下起垡
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + bladeFastVibe;
this.el.setAttribute("opacity", "1.0");
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + fastVibe;
} else if (p < 0.74) {
// 二段抖条斜面延伸至紧凑两螺旋末端 (620, 315) -> (815, 230)
const t = (p - 0.55) / 0.19;
x = 620 + (815 - 620) * t;
const chainLineY = 315 + (230 - 315) * t;
y = chainLineY - this.ry * 0.9 + fastVibe * 0.85;
} else if (p < 0.84) {
// 在二段末端顺畅从紧凑下辊下方间隙滚过进入溜槽 (815, 230) -> (865, 278)
const t = (p - 0.74) / 0.10;
x = 815 + (865 - 815) * t;
y = 230 + (278 - 230) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (865, 278) -> (935, 355)
const t = (p - 0.84) / 0.09;
x = 865 + (935 - 865) * t;
y = 278 + (355 - 278) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:在振动挖掘铲处感受4倍高频强震抬起,在二段末端紧凑两螺旋处被对转咬合排向机侧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.phaseSeed = Math.random() * 10;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 2.8 + Math.cos(vibePhase * 4.5) * 1.0;
const bladeFastVibe = Math.sin(bladeVibePhase * 4.0 + this.phaseSeed) * 2.5;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t + (t > 0.6 ? bladeFastVibe * 0.5 : 0);
stemAngle = 10;
} else if (p < 0.72) {
const t = (p - 0.20) / 0.52;
x = 320 + (800 - 320) * t;
const chainY = 425 + (230 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + fastVibe;
stemAngle = -15 - t * 25 + Math.sin(vibePhase * 2.5) * 5;
} else if (p < 0.86) {
// 在二段末端紧凑螺旋中缝 (815, 230) 咬入并抛向排秧口
const t = (p - 0.72) / 0.14;
x = 800 + (900 - 800) * t;
y = 230 + (125 - 230) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 900 + 55 * t;
y = 125 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(vibePhase * 2.0 + this.phaseSeed) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(vibePhase * 2.0) * 1.2;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 160 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
vibePhase += dt * 0.015 * timeScale;
// 铲体振动速度加快4倍
bladeVibePhase += dt * 0.060 * timeScale;
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
const bFreq = (32 * timeScale).toFixed(0);
document.getElementById('val-blade-freq').innerText = `${bFreq} Hz (4倍高频强震)`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
<!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>
:root {
--bg-dark: #090d14;
--panel-bg: rgba(13, 20, 32, 0.78);
--panel-border: rgba(56, 189, 248, 0.2);
--accent-cyan: #38bdf8;
--accent-gold: #f59e0b;
--accent-emerald: #10b981;
--accent-vine: #22c55e;
--soil-color: #854d0e;
--text-dim: #94a3b8;
--text-bright: #f1f5f9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: var(--bg-dark);
color: var(--text-bright);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
overflow: hidden;
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
justify-content: space-between;
background-image:
radial-gradient(circle at 50% 30%, rgba(56, 189, 248, 0.05) 0%, transparent 70%),
linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 顶部状态栏 */
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
z-index: 10;
pointer-events: none;
}
.title-group h1 {
font-size: 15px;
font-weight: 600;
letter-spacing: 0.5px;
color: var(--text-bright);
display: flex;
align-items: center;
gap: 8px;
}
.title-group h1 .tag {
font-size: 10px;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-vine);
border: 1px solid var(--accent-vine);
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.stats-badges {
display: flex;
gap: 12px;
}
.badge {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(8px);
padding: 4px 10px;
border-radius: 6px;
font-size: 11px;
color: var(--text-dim);
display: flex;
align-items: center;
gap: 6px;
}
.badge span.val {
color: var(--accent-emerald);
font-weight: 600;
font-family: monospace;
}
/* 中央核心动画区 */
.stage-container {
flex: 1;
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
overflow: hidden;
}
#viewport-svg {
width: 100%;
height: 100%;
max-width: 1400px;
max-height: 820px;
will-change: transform;
}
/* 底部控制与图例 */
.bottom-bar {
display: flex;
justify-content: space-between;
align-items: flex-end;
padding: 12px 24px 16px;
z-index: 10;
}
.legend-card {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 14px;
font-size: 11px;
color: var(--text-dim);
display: flex;
gap: 14px;
}
.legend-item {
display: flex;
align-items: center;
gap: 6px;
}
.legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.controls-panel {
background: var(--panel-bg);
border: 1px solid var(--panel-border);
backdrop-filter: blur(10px);
border-radius: 8px;
padding: 8px 16px;
display: flex;
align-items: center;
gap: 16px;
font-size: 11px;
}
.ctrl-item {
display: flex;
align-items: center;
gap: 8px;
color: var(--text-dim);
}
.ctrl-item input[type="range"] {
-webkit-appearance: none;
width: 80px;
height: 4px;
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
outline: none;
}
.ctrl-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
}
.btn-toggle {
background: rgba(56, 189, 248, 0.12);
border: 1px solid var(--panel-border);
color: var(--accent-cyan);
padding: 4px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 11px;
transition: all 0.2s;
}
.btn-toggle:hover {
background: rgba(56, 189, 248, 0.25);
}
.rot-cw {
transform-origin: center;
animation: spin-cw 10s linear infinite;
}
@keyframes spin-cw {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* 挖掘铲高频强力振动特效(4倍高频强震) */
.vibrating-blade-fast {
animation: vib-blade 0.03s linear infinite alternate;
}
@keyframes vib-blade {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(1.4px, -0.9px) rotate(0.35deg); }
100% { transform: translate(-1.2px, 1.1px) rotate(-0.35deg); }
}
/* 杆条振动微动特效(3倍快振) */
.chain-vibrating {
animation: chain-vib 0.133s ease-in-out infinite alternate;
}
@keyframes chain-vib {
0% { transform: translateY(0px); }
100% { transform: translateY(-1.4px); }
}
.comb-flutter {
transform-origin: top center;
animation: flutter 0.4s ease-in-out infinite alternate;
}
@keyframes flutter {
0% { transform: rotate(0deg); }
100% { transform: rotate(2.5deg); }
}
/* 主图上排秧辊螺旋棱轴向走丝动态效果 */
.main-screw-flow-upper {
animation: mainScrewFlowU 6s linear infinite;
}
@keyframes mainScrewFlowU {
from { transform: translateX(0px); }
to { transform: translateX(20px); }
}
.main-screw-flow-lower {
animation: mainScrewFlowL 6s linear infinite;
}
@keyframes mainScrewFlowL {
from { transform: translateX(0px); }
to { transform: translateX(-20px); }
}
/* 局部放大特写镜中的螺旋轴向平移动画 */
.screw-axial-flow {
animation: screwFlow 5.5s linear infinite;
}
@keyframes screwFlow {
from { transform: translateX(0px); }
to { transform: translateX(24px); }
}
</style>
</head>
<body>
<!-- 顶部状态栏 -->
<header class="top-bar">
<div class="title-group">
<h1>
一体化低损土薯挖掘分离系统
<span class="tag">对转螺旋排秧 · 防缠绕分流</span>
</h1>
</div>
<div class="stats-badges">
<div class="badge">挖掘深度: <span class="val" id="val-depth">150 mm (限深轮定深)</span></div>
<div class="badge">铲刃震频: <span class="val" id="val-blade-freq">32 Hz (4倍高频强震)</span></div>
<div class="badge">土壤分离: <span class="val">杆条缝隙快速筛落</span></div>
<div class="badge">漏薯与夹带率: <span class="val">< 0.05%</span></div>
</div>
</header>
<!-- 中央核心 SVG 动画舞台 -->
<main class="stage-container">
<svg id="viewport-svg" viewBox="0 0 1200 600" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- 材质与渐变定义 -->
<linearGradient id="soilGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#78350f" stop-opacity="0.85" />
<stop offset="100%" stop-color="#2d1305" stop-opacity="0.95" />
</linearGradient>
<linearGradient id="soilCutGrad" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#854d0e" stop-opacity="0.9" />
<stop offset="100%" stop-color="#78350f" stop-opacity="0.4" />
</linearGradient>
<linearGradient id="bladeGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#38bdf8" />
<stop offset="100%" stop-color="#0284c7" />
</linearGradient>
<linearGradient id="cushionGrad" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="#10b981" />
<stop offset="100%" stop-color="#047857" />
</linearGradient>
<!-- 机械金属圆柱辊材质渐变 -->
<linearGradient id="metalRollerGrad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#1e293b" />
<stop offset="100%" stop-color="#0f172a" />
</linearGradient>
<!-- 黄色土豆渐变质感 -->
<radialGradient id="potatoGrad" cx="35%" cy="35%" r="65%">
<stop offset="0%" stop-color="#fde047" />
<stop offset="60%" stop-color="#eab308" />
<stop offset="100%" stop-color="#ca8a04" />
</radialGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 主图排秧圆柱辊裁剪区域 -->
<clipPath id="upperRollerCylinderClip">
<rect x="-40" y="-13" width="80" height="26" rx="4"/>
</clipPath>
<clipPath id="lowerRollerCylinderClip">
<rect x="-36" y="-11" width="72" height="22" rx="4"/>
</clipPath>
<!-- 局部放大镜裁剪圆形路径 -->
<clipPath id="zoomClip">
<circle cx="560" cy="115" r="95" />
</clipPath>
</defs>
<!-- 1. 背景网格与基准参考线 -->
<g stroke="rgba(255,255,255,0.04)" stroke-width="1" stroke-dasharray="4 4">
<line x1="20" y1="420" x2="1150" y2="420" />
<line x1="20" y1="480" x2="1150" y2="480" />
</g>
<!-- 2. 地下原状土层与地表剖面 -->
<g id="ground-layer">
<path d="M 20 420 L 290 420 L 285 480 L 20 480 Z" fill="url(#soilGrad)" />
<rect x="20" y="480" width="1130" height="100" fill="#240e04" />
<line x1="20" y1="480" x2="1150" y2="480" stroke="#78350f" stroke-width="2" stroke-dasharray="6 3" />
<text x="50" y="525" fill="#64748b" font-size="10">未扰动硬土底盘 (挖掘深度 15cm 基准面)</text>
<!-- 地表植被/秧苗残余线 -->
<path d="M 20 420 L 290 420" stroke="#16a34a" stroke-width="3.5" stroke-dasharray="8 4" opacity="0.8"/>
<!-- 铲刃切土剖面动态土垡流动区 -->
<path d="M 285 480 Q 305 450 380 435 L 430 405 L 360 460 Z" fill="url(#soilCutGrad)" opacity="0.85" />
<!-- 漏土回填区 -->
<path d="M 370 480 Q 550 460 780 460 L 780 580 L 370 580 Z" fill="#381604" opacity="0.9"/>
<text x="490" y="515" fill="#a16207" font-size="11" letter-spacing="1">【土壤原位粉碎回填区】自然漏回田间</text>
</g>
<!-- 3. 机械核心运动部件层 -->
<!-- [A] 限深轮系统 -->
<g id="depth-wheel" transform="translate(210, 370)">
<line x1="0" y1="0" x2="-25" y2="-60" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<line x1="-25" y1="-60" x2="40" y2="-60" stroke="#64748b" stroke-width="8" stroke-linecap="round"/>
<g id="wheel-rot" class="rot-cw">
<circle cx="0" cy="0" r="48" fill="none" stroke="#38bdf8" stroke-width="3.5"/>
<circle cx="0" cy="0" r="32" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="4 2"/>
<line x1="-48" y1="0" x2="48" y2="0" stroke="#38bdf8" stroke-width="2"/>
<line x1="0" y1="-48" x2="0" y2="48" stroke="#38bdf8" stroke-width="2"/>
<circle cx="0" cy="0" r="6" fill="#38bdf8"/>
</g>
<text x="-70" y="-75" fill="#38bdf8" font-size="10" font-weight="bold">限深轮 (锁定铲刃入土深度 15cm)</text>
</g>
<!-- [B] 振动挖掘铲机构 (4倍高频强震) -->
<g id="vibrating-blade-group" class="vibrating-blade-fast">
<path d="M 280 482 L 375 450 L 440 405 L 420 395 L 355 435 L 265 470 Z" fill="url(#bladeGrad)" filter="url(#glow)"/>
<polygon points="265,470 295,476 280,482" fill="#e0f2fe" />
<g transform="translate(390, 425)">
<path d="M -18 0 Q 0 -22 18 0" fill="none" stroke="#f59e0b" stroke-width="2.5" stroke-dasharray="2 2"/>
</g>
<text x="260" y="515" fill="#38bdf8" font-size="10" font-weight="bold">20°入土角·振动挖掘铲 (4倍高频强震)</text>
</g>
<!-- [C] 两段式杆条抖动链条 (二段抖条延伸至紧凑两螺旋中间 800, 230) -->
<g id="conveyor-system">
<g class="chain-vibrating">
<!-- 一段抖条导轨 -->
<path d="M 440 405 L 600 315" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 440 420 L 600 330" stroke="#64748b" stroke-width="2.5"/>
<!-- 一段与二段之间的连接导轨支架 -->
<line x1="600" y1="315" x2="630" y2="305" stroke="#38bdf8" stroke-width="2" stroke-dasharray="2 2"/>
<!-- 二段抖条:斜面平稳延伸至紧凑两螺旋中缝前端 (800, 230) -->
<path d="M 630 305 L 800 230" stroke="#38bdf8" stroke-width="3.5" stroke-dasharray="8 6"/>
<path d="M 630 320 L 800 245" stroke="#64748b" stroke-width="2.5"/>
<!-- 均匀杆条排 -->
<line x1="470" y1="388" x2="470" y2="402" stroke="#38bdf8" stroke-width="2"/>
<line x1="510" y1="365" x2="510" y2="380" stroke="#38bdf8" stroke-width="2"/>
<line x1="550" y1="343" x2="550" y2="358" stroke="#38bdf8" stroke-width="2"/>
<line x1="675" y1="285" x2="675" y2="300" stroke="#38bdf8" stroke-width="2"/>
<line x1="735" y1="258" x2="735" y2="273" stroke="#38bdf8" stroke-width="2"/>
</g>
<text x="460" y="375" fill="#94a3b8" font-size="10" transform="rotate(-29 460 375)">一段杆条抖动链 (35mm间距·土落)</text>
<text x="665" y="285" fill="#38bdf8" font-size="10" font-weight="500" transform="rotate(-23 665 285)">二段抖条末端正对紧凑螺旋中缝 →</text>
</g>
<!-- [D] 弹性梳齿挡帘 -->
<g id="comb-curtain" transform="translate(760, 160)">
<path d="M 0 0 L 25 0" stroke="#64748b" stroke-width="6" stroke-linecap="round"/>
<g class="comb-flutter" stroke="#22c55e" stroke-width="2.5" stroke-linecap="round">
<line x1="3" y1="0" x2="6" y2="52" />
<line x1="9" y1="0" x2="13" y2="50" />
<line x1="15" y1="0" x2="20" y2="54" />
<line x1="21" y1="0" x2="27" y2="48" />
</g>
<text x="-40" y="-8" fill="#22c55e" font-size="10" font-weight="500">弹性梳齿挡帘 (挑秧导流)</text>
</g>
<!-- [E] 主视图核心:两个螺旋排秧辊机构 -->
<g id="vine-separator-unit">
<!-- 侧排秧导槽 -->
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#15803d" stroke-width="8" stroke-linecap="round" opacity="0.6"/>
<path d="M 815 210 Q 860 160 905 125" fill="none" stroke="#22c55e" stroke-width="3" stroke-dasharray="6 3" filter="url(#glow)"/>
<text x="855" y="115" fill="#22c55e" font-size="10" font-weight="bold">【机侧排秧口】螺旋轴向抛秧 →</text>
<!-- 上螺旋棱圆柱辊 -->
<g transform="translate(815, 210)">
<rect x="-42" y="-13" width="84" height="26" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-42" y1="0" x2="-48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="42" y1="0" x2="48" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#upperRollerCylinderClip)">
<g class="main-screw-flow-upper" stroke="#86efac" stroke-width="2.5" stroke-linecap="round" opacity="0.95">
<line x1="-55" y1="-13" x2="-35" y2="13" />
<line x1="-35" y1="-13" x2="-15" y2="13" />
<line x1="-15" y1="-13" x2="5" y2="13" />
<line x1="5" y1="-13" x2="25" y2="13" />
<line x1="25" y1="-13" x2="45" y2="13" />
<line x1="45" y1="-13" x2="65" y2="13" />
</g>
</g>
<text x="46" y="-4" fill="#86efac" font-size="9" font-weight="bold">上螺旋排秧辊 (80 r/min →)</text>
</g>
<!-- 紧凑咬合夹秧中缝流线 -->
<g transform="translate(815, 230)" opacity="0.9">
<line x1="-25" y1="0" x2="35" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="3 2" />
<polygon points="40,0 33,-3 33,3" fill="#22c55e" />
</g>
<!-- 下螺旋棱圆柱辊 -->
<g transform="translate(815, 250)">
<rect x="-38" y="-11" width="76" height="22" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="1.5"/>
<line x1="-38" y1="0" x2="-44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<line x1="38" y1="0" x2="44" y2="0" stroke="#64748b" stroke-width="4" stroke-linecap="round"/>
<g clip-path="url(#lowerRollerCylinderClip)">
<g class="main-screw-flow-lower" stroke="#86efac" stroke-width="2.2" stroke-linecap="round" opacity="0.95">
<line x1="-50" y1="11" x2="-30" y2="-11" />
<line x1="-30" y1="11" x2="-10" y2="-11" />
<line x1="-10" y1="11" x2="10" y2="-11" />
<line x1="10" y1="11" x2="30" y2="-11" />
<line x1="30" y1="11" x2="50" y2="-11" />
<line x1="50" y1="11" x2="70" y2="-11" />
</g>
</g>
<text x="42" y="5" fill="#86efac" font-size="9" font-weight="bold">← 下螺旋排秧辊 (紧凑窄缝)</text>
</g>
<!-- 导流通道标注 -->
<rect x="775" y="278" width="130" height="20" rx="4" fill="rgba(6, 78, 59, 0.75)" stroke="#059669" stroke-width="1"/>
<text x="781" y="292" fill="#a7f3d0" font-size="9.5">▼ 辊下间隙: 黄色土豆超慢速滚过</text>
</g>
<!-- [F] 柔性橡胶缓冲溜槽 -->
<g id="buffer-chute" transform="translate(865, 278)">
<path d="M 0 0 L 60 40 L 75 80" fill="none" stroke="#475569" stroke-width="8" stroke-linecap="round"/>
<path d="M -3 -3 L 57 37 L 72 77" fill="none" stroke="url(#cushionGrad)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
<text x="25" y="22" fill="#10b981" font-size="10" font-weight="500">35° 柔性缓冲溜槽</text>
<text x="25" y="36" fill="#6ee7b7" font-size="9">改自由落体为低动能滑动</text>
</g>
<!-- [G] 收集料箱 (集装箱) -->
<g id="collection-box" transform="translate(935, 330)">
<path d="M 0 50 L 0 160 L 180 160 L 180 30" fill="none" stroke="#475569" stroke-width="5" stroke-linejoin="round"/>
<rect x="5" y="148" width="170" height="10" rx="3" fill="#059669" filter="url(#glow)"/>
<path d="M 5 60 L 45 110 L 5 145" fill="none" stroke="#10b981" stroke-width="4" stroke-linecap="round"/>
<text x="25" y="180" fill="#10b981" font-size="10">集装箱 (10mm 减振底垫 + 导流板)</text>
</g>
<!-- 动态层:黄色土豆贴面抖动上移、抖落细泥土、杂草/茎蔓震动上移与排秧 -->
<g id="dynamic-soil-drops"></g>
<g id="dynamic-potatoes"></g>
<g id="dynamic-vines"></g>
<!-- [H] 局部放大特写镜 -->
<g id="detail-zoom-lens">
<path d="M 790 230 L 655 115" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<path d="M 815 278 L 655 160" stroke="#38bdf8" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.4" />
<circle cx="560" cy="115" r="95" fill="#0b1329" stroke="#22c55e" stroke-width="3" filter="url(#glow)"/>
<g clip-path="url(#zoomClip)">
<line x1="460" y1="115" x2="660" y2="115" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<line x1="560" y1="15" x2="560" y2="215" stroke="rgba(255,255,255,0.06)" stroke-dasharray="2 2" />
<!-- 特写:紧凑上螺旋辊 -->
<g transform="translate(560, 75)">
<rect x="-70" y="-15" width="140" height="30" rx="5" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3.5" stroke-linecap="round">
<line x1="-80" y1="-15" x2="-62" y2="15" />
<line x1="-56" y1="-15" x2="-38" y2="15" />
<line x1="-32" y1="-15" x2="-14" y2="15" />
<line x1="-8" y1="-15" x2="10" y2="15" />
<line x1="16" y1="-15" x2="34" y2="15" />
<line x1="40" y1="-15" x2="58" y2="15" />
<line x1="64" y1="-15" x2="82" y2="15" />
</g>
</g>
<!-- 特写:紧凑下螺旋辊 -->
<g transform="translate(560, 115)">
<rect x="-70" y="-12" width="140" height="24" rx="4" fill="url(#metalRollerGrad)" stroke="#38bdf8" stroke-width="2"/>
<g class="screw-axial-flow" stroke="#86efac" stroke-width="3" stroke-linecap="round">
<line x1="-80" y1="12" x2="-62" y2="-12" />
<line x1="-56" y1="12" x2="-38" y2="-12" />
<line x1="-32" y1="12" x2="-14" y2="-12" />
<line x1="-8" y1="12" x2="10" y2="-12" />
<line x1="16" y1="12" x2="34" y2="-12" />
<line x1="40" y1="12" x2="58" y2="-12" />
<line x1="64" y1="12" x2="82" y2="-12" />
</g>
</g>
<!-- 咬缝与轴向推秧箭头指示 -->
<g transform="translate(560, 95)" opacity="0.9">
<line x1="-60" y1="0" x2="60" y2="0" stroke="#22c55e" stroke-width="1.5" stroke-dasharray="4 2"/>
<path d="M 0 0 L 45 0" stroke="#38bdf8" stroke-width="2" stroke-linecap="round" marker-end="url(#glow)"/>
<polygon points="50,0 42,-4 42,4" fill="#38bdf8"/>
<text x="-48" y="-3" fill="#86efac" font-size="8.5" font-weight="bold">紧凑夹秧缝 (螺旋横向轴推 →)</text>
</g>
<!-- 特写:辊下间隙薯块通道 -->
<g transform="translate(560, 160)">
<rect x="-75" y="-16" width="150" height="32" fill="rgba(56, 189, 248, 0.08)" stroke="rgba(56, 189, 248, 0.3)" stroke-dasharray="3 3"/>
<text x="-65" y="-3" fill="#38bdf8" font-size="8.5">辊下通过间隙</text>
<text x="-65" y="9" fill="#94a3b8" font-size="8">黄色土豆超慢速滚过 →</text>
</g>
<!-- 局部特写动态层 -->
<g id="lens-dynamic-elements"></g>
</g>
<!-- 镜框金属质感边缘与标题铭牌 -->
<circle cx="560" cy="115" r="95" fill="none" stroke="#22c55e" stroke-width="3" opacity="0.8"/>
<rect x="495" y="200" width="130" height="20" rx="10" fill="#0f172a" stroke="#22c55e" stroke-width="1.5"/>
<text x="507" y="214" fill="#86efac" font-size="10" font-weight="bold">【排秧机构局部特写】</text>
</g>
<!-- 引导流线 -->
<g id="process-flow-arrows" opacity="0.8">
<path d="M 160 455 Q 240 460 270 472" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-dasharray="5 3"/>
<polygon points="275,475 264,468 266,478" fill="#38bdf8"/>
<path d="M 285 472 Q 345 440 430 405" fill="none" stroke="#38bdf8" stroke-width="2" stroke-dasharray="4 4"/>
</g>
</svg>
</main>
<!-- 底部控制与图例 -->
<footer class="bottom-bar">
<div class="legend-card">
<div class="legend-item">
<div class="legend-dot" style="background: #38bdf8;"></div>
<span>切土抬垡 (4倍高频强震) 与两段筛分</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #eab308;"></div>
<span>黄色土豆 (抖落泥土 → 穿过紧凑螺旋 → 进箱)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #a16207;"></div>
<span>泥土细粉/碎块 (抖条缝隙自然筛落回填)</span>
</div>
<div class="legend-item">
<div class="legend-dot" style="background: #22c55e;"></div>
<span>茎秆/叶片 (二段末端上下螺旋对咬排秧)</span>
</div>
</div>
<div class="controls-panel">
<div class="ctrl-item">
<label for="speed-range">作业线速</label>
<input type="range" id="speed-range" min="0.5" max="2.0" step="0.1" value="1.0">
</div>
<div class="ctrl-item">
<label for="flow-range">进料密度</label>
<input type="range" id="flow-range" min="1" max="4" step="1" value="2">
</div>
<button class="btn-toggle" id="btn-pause">暂停运转</button>
</div>
</footer>
<script>
const potatoGroup = document.getElementById('dynamic-potatoes');
const vineGroup = document.getElementById('dynamic-vines');
const soilDropGroup = document.getElementById('dynamic-soil-drops');
const lensDynamicGroup = document.getElementById('lens-dynamic-elements');
const speedRange = document.getElementById('speed-range');
const flowRange = document.getElementById('flow-range');
const btnPause = document.getElementById('btn-pause');
let isRunning = true;
let timeScale = 1.0;
let spawnCounter = 0;
let vineSpawnCounter = 0;
let spawnInterval = 375;
const potatoes = [];
const vines = [];
const soilDrops = [];
const collectedPotatoes = [];
const lensElements = [];
// 高频抖动相位累加器(3倍快抖)
let vibePhase = 0;
// 挖掘铲4倍高频振动相位累加器
let bladeVibePhase = 0;
// 抖落泥土颗粒类(细小土色线粒/碎土粒,从抖条缝隙向下自然落下,绝非黑球)
class SoilDrop {
constructor(x, y) {
this.x = x + (Math.random() - 0.5) * 8;
this.y = y + (Math.random() - 0.5) * 4;
this.vy = 1.2 + Math.random() * 1.5;
this.vx = (Math.random() - 0.5) * 0.4;
this.length = 3.5 + Math.random() * 3.0;
this.opacity = 0.75 + Math.random() * 0.2;
this.isDone = false;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "line");
this.el.setAttribute("stroke", Math.random() > 0.4 ? "#a16207" : "#b45309");
this.el.setAttribute("stroke-width", "1.6");
this.el.setAttribute("stroke-linecap", "round");
soilDropGroup.appendChild(this.el);
}
update(dt) {
this.x += this.vx * timeScale;
this.y += this.vy * timeScale;
this.vy += 0.08 * timeScale; // 重力沉降
this.el.setAttribute("x1", this.x);
this.el.setAttribute("y1", this.y);
this.el.setAttribute("x2", this.x);
this.el.setAttribute("y2", this.y + this.length);
this.el.setAttribute("opacity", this.opacity);
this.opacity -= 0.02 * timeScale;
if (this.opacity <= 0 || this.y > 510) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 黄色土豆类:慢速5倍平移,二段抖条延伸并正对紧凑两螺旋 (815, 230) 中间
class Potato {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.rx = 13 + Math.random() * 3.5;
this.ry = 9 + Math.random() * 2.5;
this.angle = Math.random() * 360;
this.rotSpeed = (Math.random() - 0.5) * 0.08;
this.embedDepth = 452 + Math.random() * 8;
this.phaseSeed = Math.random() * 10;
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", this.rx);
this.el.setAttribute("ry", this.ry);
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
potatoGroup.appendChild(this.el);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
this.angle += this.rotSpeed * timeScale;
let x, y;
const p = this.progress;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 0.8;
const bladeFastVibe = Math.sin(bladeVibePhase * 4.0 + this.phaseSeed) * 1.2;
if (p < 0.18) {
const t = p / 0.18;
x = 40 + (265 - 40) * t;
y = this.embedDepth;
this.el.setAttribute("opacity", "0.9");
} else if (p < 0.30) {
// 挖掘铲切土抬升阶段:受限深轮定深并在4倍高频强震下起垡
const t = (p - 0.18) / 0.12;
x = 265 + (440 - 265) * t;
const bladeBaseY = 472 + (405 - 472) * t;
y = bladeBaseY - this.ry * 0.85 + bladeFastVibe;
this.el.setAttribute("opacity", "1.0");
// 铲尖强震抖落少量泥土
if (Math.random() < 0.15 * timeScale) {
soilDrops.push(new SoilDrop(x, y + this.ry));
}
} else if (p < 0.55) {
// 一段杆条抖动链 (440, 405) -> (620, 315)
const t = (p - 0.30) / 0.25;
x = 440 + (620 - 440) * t;
const chainLineY = 405 + (315 - 405) * t;
y = chainLineY - this.ry * 0.9 + fastVibe;
// 一段抖条缝隙大量抖落泥土
if (Math.random() < 0.35 * timeScale) {
soilDrops.push(new SoilDrop(x, y + this.ry + 2));
}
} else if (p < 0.74) {
// 二段抖条斜面延伸至紧凑两螺旋末端 (620, 315) -> (815, 230)
const t = (p - 0.55) / 0.19;
x = 620 + (815 - 620) * t;
const chainLineY = 315 + (230 - 315) * t;
y = chainLineY - this.ry * 0.9 + fastVibe * 0.85;
// 二段抖条继续筛落残余细土
if (Math.random() < 0.20 * timeScale) {
soilDrops.push(new SoilDrop(x, y + this.ry + 2));
}
} else if (p < 0.84) {
// 在二段末端顺畅从紧凑下辊下方间隙滚过进入溜槽 (815, 230) -> (865, 278)
const t = (p - 0.74) / 0.10;
x = 815 + (865 - 815) * t;
y = 230 + (278 - 230) * t + Math.sin(t * Math.PI) * 0.8;
} else if (p < 0.93) {
// 35° 柔性橡胶溜槽滑落 (865, 278) -> (935, 355)
const t = (p - 0.84) / 0.09;
x = 865 + (935 - 865) * t;
y = 278 + (355 - 278) * (t * t);
} else if (p < 1.0) {
// 顺着导流板慢慢掉进集装箱
const t = (p - 0.93) / 0.07;
const targetSlot = Math.min(1080, 955 + (potatoes.length % 7) * 16);
x = 935 + (targetSlot - 935) * t;
y = 355 + (460 - 355) * t;
} else {
this.isDone = true;
x = 955 + (potatoes.length % 7) * 16;
y = 460 - Math.floor((collectedPotatoes.length / 7)) * 12;
}
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${this.angle} ${x} ${y})`);
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 细长秧蔓条类:在二段末端紧凑两螺旋 (815, 230) 处被对转咬合排向机侧
class VineEntity {
constructor(initialProgress = 0) {
this.progress = initialProgress;
this.stemLength = 45 + Math.random() * 15;
this.phaseSeed = Math.random() * 10;
this.group = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.stem = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.stem.setAttribute("stroke", "#16a34a");
this.stem.setAttribute("stroke-width", "2.6");
this.stem.setAttribute("stroke-linecap", "round");
this.stem.setAttribute("fill", "none");
this.group.appendChild(this.stem);
this.branch1 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch1.setAttribute("stroke", "#22c55e");
this.branch1.setAttribute("stroke-width", "1.5");
this.branch1.setAttribute("stroke-linecap", "round");
this.branch1.setAttribute("fill", "none");
this.group.appendChild(this.branch1);
this.branch2 = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.branch2.setAttribute("stroke", "#4ade80");
this.branch2.setAttribute("stroke-width", "1.5");
this.branch2.setAttribute("stroke-linecap", "round");
this.branch2.setAttribute("fill", "none");
this.group.appendChild(this.branch2);
vineGroup.appendChild(this.group);
this.isDone = false;
}
update(dt) {
this.progress += dt * 0.00018 * timeScale;
const p = this.progress;
let x, y, stemAngle = 0, opacity = 1.0;
const fastVibe = Math.sin(vibePhase * 3.0 + this.phaseSeed) * 2.8 + Math.cos(vibePhase * 4.5) * 1.0;
if (p < 0.20) {
const t = p / 0.20;
x = 60 + (320 - 60) * t;
y = 412 + (425 - 412) * t;
stemAngle = 10;
} else if (p < 0.72) {
const t = (p - 0.20) / 0.52;
x = 320 + (800 - 320) * t;
const chainY = 425 + (230 - 425) * t;
const liftByComb = t > 0.75 ? (t - 0.75) * 50 : 0;
y = chainY - 18 - liftByComb + fastVibe;
stemAngle = -15 - t * 25 + Math.sin(vibePhase * 2.5) * 5;
} else if (p < 0.86) {
// 在二段末端紧凑螺旋中缝 (815, 230) 咬入并抛向排秧口
const t = (p - 0.72) / 0.14;
x = 800 + (900 - 800) * t;
y = 230 + (125 - 230) * Math.sin(t * (Math.PI / 2));
stemAngle = -35 - t * 45;
this.stem.setAttribute("stroke", "#86efac");
} else if (p < 1.0) {
const t = (p - 0.86) / 0.14;
x = 900 + 55 * t;
y = 125 + 45 * (t * t);
stemAngle = -90 - t * 20;
opacity = Math.max(0, 1.0 - t * 1.2);
} else {
this.isDone = true;
}
const rad = stemAngle * Math.PI / 180;
const dx = Math.cos(rad) * (this.stemLength / 2);
const dy = Math.sin(rad) * (this.stemLength / 2);
const wave = Math.sin(vibePhase * 2.0 + this.phaseSeed) * 3.5;
const d = `M ${x - dx} ${y - dy} Q ${x + wave} ${y + wave * 0.5} ${x + dx} ${y + dy}`;
this.stem.setAttribute("d", d);
const midX = x - dx * 0.2;
const midY = y - dy * 0.2;
this.branch1.setAttribute("d", `M ${midX} ${midY} Q ${midX - 6} ${midY - 8} ${midX - 10} ${midY - 12}`);
const topX = x + dx * 0.3;
const topY = y + dy * 0.3;
this.branch2.setAttribute("d", `M ${topX} ${topY} Q ${topX + 8} ${topY + 6} ${topX + 12} ${topY + 10}`);
this.group.setAttribute("opacity", opacity);
}
destroy() {
if (this.group.parentNode) {
this.group.parentNode.removeChild(this.group);
}
}
}
// 特写镜头内动态机理类
class LensMechanismDemo {
constructor(type) {
this.type = type;
this.progress = 0;
this.isDone = false;
if (this.type === 'vine') {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el.setAttribute("stroke", "#4ade80");
this.el.setAttribute("stroke-width", "3.5");
this.el.setAttribute("stroke-linecap", "round");
this.el.setAttribute("fill", "none");
this.el.setAttribute("filter", "url(#glow)");
} else {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "ellipse");
this.el.setAttribute("rx", "11");
this.el.setAttribute("ry", "8");
this.el.setAttribute("fill", "url(#potatoGrad)");
this.el.setAttribute("stroke", "#a16207");
this.el.setAttribute("stroke-width", "1.5");
}
lensDynamicGroup.appendChild(this.el);
}
update(dt) {
this.progress += dt * 0.00036 * timeScale;
const p = this.progress;
if (this.type === 'vine') {
const x = 475 + (645 - 475) * p;
const y = 95 + Math.sin(vibePhase * 2.0) * 1.2;
const d = `M ${x - 16} ${y + 2} Q ${x} ${y - 4} ${x + 16} ${y + 3}`;
this.el.setAttribute("d", d);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
} else {
const x = 475 + (645 - 475) * p;
const y = 160 + Math.sin(p * Math.PI) * 1.0;
this.el.setAttribute("cx", x);
this.el.setAttribute("cy", y);
this.el.setAttribute("transform", `rotate(${p * 240} ${x} ${y})`);
this.el.setAttribute("opacity", p > 0.85 ? Math.max(0, (1 - p) / 0.15) : 1.0);
}
if (p >= 1.0) {
this.isDone = true;
}
}
destroy() {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
}
}
// 主动画循环
let lastTime = performance.now();
let lensSpawnTimer = 0;
function animate(currentTime) {
const dt = Math.min(32, currentTime - lastTime);
lastTime = currentTime;
if (isRunning) {
vibePhase += dt * 0.015 * timeScale;
bladeVibePhase += dt * 0.060 * timeScale;
spawnCounter += timeScale;
vineSpawnCounter += timeScale;
lensSpawnTimer += timeScale;
// 抖条整体区域环境持续筛落细微泥土颗粒
if (Math.random() < 0.25 * timeScale) {
// 一段抖条下落泥土
const t1 = Math.random();
const dropX1 = 450 + (600 - 450) * t1;
const dropY1 = 405 + (315 - 405) * t1 + 8;
soilDrops.push(new SoilDrop(dropX1, dropY1));
}
if (Math.random() < 0.15 * timeScale) {
// 二段抖条下落泥土
const t2 = Math.random();
const dropX2 = 640 + (780 - 640) * t2;
const dropY2 = 300 + (235 - 300) * t2 + 8;
soilDrops.push(new SoilDrop(dropX2, dropY2));
}
// 生成黄色土豆
if (spawnCounter >= spawnInterval) {
spawnCounter = 0;
potatoes.push(new Potato(0));
}
// 生成细长秧蔓条
if (vineSpawnCounter >= spawnInterval * 1.25) {
vineSpawnCounter = 0;
vines.push(new VineEntity(0));
}
// 局部特写镜动态
if (lensSpawnTimer >= 550) {
lensSpawnTimer = 0;
lensElements.push(new LensMechanismDemo('vine'));
setTimeout(() => {
if (isRunning) lensElements.push(new LensMechanismDemo('potato'));
}, 3000);
}
// 更新土豆
for (let i = potatoes.length - 1; i >= 0; i--) {
const p = potatoes[i];
p.update(dt);
if (p.isDone) {
collectedPotatoes.push(p);
potatoes.splice(i, 1);
if (collectedPotatoes.length > 28) {
const old = collectedPotatoes.shift();
old.destroy();
}
}
}
// 更新细长秧蔓
for (let i = vines.length - 1; i >= 0; i--) {
const v = vines[i];
v.update(dt);
if (v.isDone) {
v.destroy();
vines.splice(i, 1);
}
}
// 更新抖落泥土
for (let i = soilDrops.length - 1; i >= 0; i--) {
const drop = soilDrops[i];
drop.update(dt);
if (drop.isDone) {
drop.destroy();
soilDrops.splice(i, 1);
}
}
// 更新局部特写元素
for (let i = lensElements.length - 1; i >= 0; i--) {
const item = lensElements[i];
item.update(dt);
if (item.isDone) {
item.destroy();
lensElements.splice(i, 1);
}
}
}
requestAnimationFrame(animate);
}
// 交互响应
speedRange.addEventListener('input', (e) => {
timeScale = parseFloat(e.target.value);
const rpm = Math.round(80 * timeScale);
document.getElementById('val-rpm').innerText = `${rpm} r/min`;
const bFreq = (32 * timeScale).toFixed(0);
document.getElementById('val-blade-freq').innerText = `${bFreq} Hz (4倍高频强震)`;
});
flowRange.addEventListener('input', (e) => {
const density = parseInt(e.target.value);
spawnInterval = Math.max(200, 475 - density * 60);
});
btnPause.addEventListener('click', () => {
isRunning = !isRunning;
btnPause.innerText = isRunning ? "暂停运转" : "恢复运转";
btnPause.style.borderColor = isRunning ? "rgba(56, 189, 248, 0.2)" : "#f59e0b";
});
// 自动无缝预热启动
window.addEventListener('DOMContentLoaded', () => {
potatoes.push(new Potato(0.08));
potatoes.push(new Potato(0.26));
potatoes.push(new Potato(0.46));
potatoes.push(new Potato(0.68));
potatoes.push(new Potato(0.84));
vines.push(new VineEntity(0.14));
vines.push(new VineEntity(0.40));
vines.push(new VineEntity(0.72));
lensElements.push(new LensMechanismDemo('vine'));
lensElements[0].progress = 0.45;
requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
