独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TRIZ IFR - 隐形剪叉遮阳系统原理动画</title>
<!-- 引入特殊排版与等宽字体以提升工程美学 -->
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Noto+Sans+SC:wght@300;500;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color: #050505;
--grid-color: #171717;
--accent-cyan: #06b6d4;
--accent-cyan-glow: rgba(6, 182, 212, 0.5);
--accent-amber: #f59e0b;
--accent-amber-glow: rgba(245, 158, 11, 0.5);
--panel-bg: rgba(15, 15, 15, 0.85);
--text-main: #f8fafc;
--text-dim: #94a3b8;
--border-tech: rgba(6, 182, 212, 0.3);
--font-ui: 'Noto Sans SC', sans-serif;
--font-data: 'JetBrains Mono', monospace;
--font-title: 'Orbitron', sans-serif;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
user-select: none;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: var(--font-ui);
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-image:
linear-gradient(rgba(6, 182, 212, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(6, 182, 212, 0.03) 1px, transparent 1px);
background-size: 40px 40px;
}
.dashboard-container {
position: relative;
width: 100%;
max-width: 1400px;
height: 100%;
max-height: 900px;
display: flex;
border-radius: 16px;
box-shadow: 0 0 100px rgba(0, 0, 0, 0.8) inset,
0 0 40px rgba(6, 182, 212, 0.1);
overflow: hidden;
border: 1px solid #262626;
background: radial-gradient(circle at center, #111 0%, #000 100%);
}
/* 左侧 HUD 界面 */
.hud-panel {
position: absolute;
left: 30px;
top: 30px;
width: 320px;
z-index: 10;
display: flex;
flex-direction: column;
gap: 20px;
pointer-events: none; /* 让鼠标穿透 */
}
.hud-card {
background: var(--panel-bg);
border: 1px solid var(--border-tech);
border-radius: 8px;
padding: 20px;
backdrop-filter: blur(10px);
position: relative;
overflow: hidden;
}
.hud-card::before {
content: '';
position: absolute;
top: 0; left: 0; width: 4px; height: 100%;
background: var(--accent-cyan);
box-shadow: 0 0 10px var(--accent-cyan);
}
.hud-card.alert::before {
background: var(--accent-amber);
box-shadow: 0 0 10px var(--accent-amber);
}
.hud-title {
font-size: 14px;
color: var(--text-dim);
letter-spacing: 2px;
margin-bottom: 12px;
display: flex;
justify-content: space-between;
align-items: center;
}
.hud-title span.tag {
font-family: var(--font-title);
color: var(--accent-cyan);
font-size: 12px;
border: 1px solid var(--accent-cyan);
padding: 2px 6px;
border-radius: 4px;
}
.hud-value {
font-family: var(--font-data);
font-size: 28px;
color: var(--accent-cyan);
text-shadow: 0 0 15px var(--accent-cyan-glow);
margin-bottom: 8px;
display: flex;
align-items:baseline;
gap: 5px;
}
.hud-value.amber {
color: var(--accent-amber);
text-shadow: 0 0 15px var(--accent-amber-glow);
}
.hud-unit {
font-size: 14px;
color: var(--text-dim);
}
.hud-desc {
font-size: 13px;
line-height: 1.5;
color: #d1d5db;
}
.highlight-text {
color: var(--accent-cyan);
font-weight: 700;
}
/* 顶部标题 */
.main-title {
position: absolute;
top: 30px;
left: 50%;
transform: translateX(-50%);
text-align: center;
z-index: 10;
}
.main-title h1 {
font-family: var(--font-title);
font-size: 24px;
letter-spacing: 4px;
text-transform: uppercase;
color: #fff;
text-shadow: 0 0 20px rgba(255, 255, 255, 0.5);
margin-bottom: 8px;
}
.main-title h2 {
font-size: 14px;
color: var(--text-dim);
letter-spacing: 6px;
font-weight: 300;
}
/* 右下角交互控制 */
.controls-panel {
position: absolute;
right: 30px;
bottom: 30px;
width: 300px;
background: var(--panel-bg);
border: 1px solid #333;
border-radius: 8px;
padding: 20px;
z-index: 20;
backdrop-filter: blur(10px);
}
.control-header {
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: 12px;
color: var(--text-dim);
letter-spacing: 1px;
}
.slider-container {
position: relative;
width: 100%;
height: 6px;
background: #262626;
border-radius: 3px;
}
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 100%;
background: transparent;
position: absolute;
top: 0;
left: 0;
margin: 0;
cursor: ew-resize;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: var(--accent-cyan);
cursor: pointer;
box-shadow: 0 0 15px var(--accent-cyan);
border: 2px solid #fff;
transition: transform 0.1s;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
/* 中央可视化区域 */
.svg-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
filter: drop-shadow(0 0 20px rgba(0,0,0,0.5));
}
/* 动画元素专属样式 */
.glow-line {
stroke: var(--accent-cyan);
stroke-width: 2;
filter: drop-shadow(0 0 8px var(--accent-cyan));
}
.carbon-arm {
stroke: #1f2937;
stroke-width: 8;
stroke-linecap: round;
stroke-linejoin: round;
transition: stroke 0.3s;
}
.carbon-arm-inner {
stroke: #374151;
stroke-width: 4;
stroke-linecap: round;
stroke-linejoin: round;
}
.pivot-joint {
fill: #fff;
stroke: var(--accent-amber);
stroke-width: 2;
filter: drop-shadow(0 0 4px var(--accent-amber));
}
.lip-glow {
transition: opacity 0.3s ease, transform 0.3s ease;
}
</style>
</head>
<body>
<div class="dashboard-container">
<!-- 标题 -->
<header class="main-title">
<h1>TRIZ IFR 架构设计</h1>
<h2>微型碳纤维剪叉隐形遮阳系统</h2>
</header>
<!-- 左侧数据分析板 -->
<aside class="hud-panel">
<div class="hud-card">
<div class="hud-title">核心原理 <span class="tag">IFR</span></div>
<div class="hud-desc">
最终理想解(IFR)旨在不引入复杂组件的前提下消除矛盾。本系统采用极薄碳纤维机械臂穿透自闭合磁性硅胶唇边,实现<span class="highlight-text">结构收纳隐形</span>与<span class="highlight-text">内饰外观无孔洞</span>的完美统一。
</div>
</div>
<div class="hud-card alert" id="card-gap">
<div class="hud-title">硅胶唇边磁力状态 <span class="tag">STATUS</span></div>
<div class="hud-value amber" id="val-force">2.0 <span class="hud-unit">N</span></div>
<div class="hud-desc">状态: <span id="status-text" class="highlight-text" style="color:var(--accent-amber)">完全吸合 (无缝隙)</span></div>
<div class="hud-desc" style="margin-top: 5px; font-size:11px; opacity:0.7">磁吸硅胶条在常态下保持强力闭合,阻隔灰尘并维持内饰完整性。</div>
</div>
<div class="hud-card" id="card-arm">
<div class="hud-title">剪叉臂厚度 <span class="tag">PHYSICS</span></div>
<div class="hud-value">8.0 <span class="hud-unit">mm</span></div>
<div class="hud-desc">利用多级铝合金与碳纤维复合冲压工艺,将机械臂厚度压缩至极致,穿刺时两侧仍维持磁力吸合。</div>
</div>
</aside>
<!-- 右下角手动交互 -->
<div class="controls-panel">
<div class="control-header">
<span>动态演示控制 (AUTO)</span>
<span id="progress-percent">0%</span>
</div>
<div class="slider-container">
<input type="range" id="manual-slider" min="0" max="100" value="0">
</div>
<div style="font-size: 11px; color: #64748b; margin-top: 12px; text-align: center;">
拖动滑块可手动探索理想解机理<br>释放2秒后自动恢复运行
</div>
</div>
<!-- 核心SVG画布 -->
<main class="svg-container">
<svg id="mechanism" viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 渐变与滤镜 -->
<linearGradient id="shade-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="rgba(6, 182, 212, 0.4)" />
<stop offset="100%" stop-color="rgba(6, 182, 212, 0.05)" />
</linearGradient>
<linearGradient id="lip-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#1e293b" />
<stop offset="45%" stop-color="#334155" />
<stop offset="50%" stop-color="#06b6d4" />
<stop offset="55%" stop-color="#334155" />
<stop offset="100%" stop-color="#1e293b" />
</linearGradient>
<radialGradient id="motor-glow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="rgba(245, 158, 11, 0.8)"/>
<stop offset="100%" stop-color="rgba(245, 158, 11, 0)"/>
</radialGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="4" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- 碳纤维纹理 -->
<pattern id="carbon" width="4" height="4" patternUnits="userSpaceOnUse">
<rect width="4" height="4" fill="#171717"/>
<path d="M0,4 l4,-4" stroke="#262626" stroke-width="1"/>
</pattern>
<clipPath id="zoom-clip">
<circle cx="950" cy="250" r="120" />
</clipPath>
</defs>
<!-- 背景导视线段 -->
<g stroke="#1e293b" stroke-width="1" stroke-dasharray="4 4">
<line x1="600" y1="50" x2="600" y2="750" />
<line x1="200" y1="550" x2="1000" y2="550" />
</g>
<!-- 车窗边框 (平行四边形变体) -->
<path d="M 350,150 L 850,150 L 950,500 L 250,500 Z"
fill="none" stroke="#334155" stroke-width="6" stroke-linejoin="round" />
<path d="M 350,150 L 850,150 L 950,500 L 250,500 Z"
fill="none" stroke="#000" stroke-width="2" stroke-linejoin="round" />
<!-- 遮阳帘布 -->
<polygon id="shade-cloth" points="250,500 950,500 950,500 250,500"
fill="url(#shade-grad)" stroke="var(--accent-cyan)" stroke-width="1" />
<!-- 磁性硅胶唇边 (门板饰条位置 Y=500) -->
<rect x="200" y="495" width="800" height="10" rx="5" fill="#111827" stroke="#334155" stroke-width="2"/>
<!-- 唇边发光指示 -->
<path id="magnetic-lip-glow" d="M 200,500 L 1000,500"
stroke="url(#lip-grad)" stroke-width="3" filter="url(#glow)" class="lip-glow"/>
<circle id="puncture-point" cx="600" cy="500" r="0" fill="none" stroke="var(--accent-cyan)" stroke-width="2" filter="url(#glow)"/>
<!-- 牵引杆 -->
<line id="traction-bar" x1="250" y1="500" x2="950" y2="500"
stroke="#94a3b8" stroke-width="6" stroke-linecap="round" />
<!-- 剪叉机械臂组 -->
<g id="scissor-group">
<!-- 通过 JS 动态生成连杆 -->
</g>
<!-- 底部驱动机构 (Y=620) -->
<g id="drive-system" transform="translate(0, 620)">
<!-- 丝杠 -->
<rect x="350" y="-5" width="500" height="10" fill="#334155" />
<!-- 丝杠螺纹效果 -->
<path d="M 350, -5 L 850, 5 M 355, -5 L 855, 5" stroke="#1e293b" stroke-width="2" stroke-dasharray="2 4"/>
<!-- 电机 -->
<circle cx="330" cy="0" r="30" fill="url(#motor-glow)" />
<rect x="290" y="-20" width="60" height="40" rx="4" fill="#1f2937" stroke="#f59e0b" stroke-width="2"/>
<g id="motor-rotor">
<circle cx="350" cy="0" r="12" fill="#334155" stroke="#f59e0b" stroke-width="2"/>
<line x1="338" y1="0" x2="362" y2="0" stroke="#f59e0b" stroke-width="2"/>
<line x1="350" y1="-12" x2="350" y2="12" stroke="#f59e0b" stroke-width="2"/>
</g>
<text x="290" y="35" font-size="10" fill="var(--accent-amber)" font-family="var(--font-data)">STEP MOTOR</text>
<!-- 滑块 -->
<rect id="block-l" x="400" y="-10" width="30" height="20" rx="3" fill="#06b6d4" />
<rect id="block-r" x="770" y="-10" width="30" height="20" rx="3" fill="#06b6d4" />
</g>
<!-- 顶部微观剖面放大镜 (Inset View) -->
<g transform="translate(0, 0)">
<circle cx="950" cy="250" r="125" fill="#050505" stroke="#334155" stroke-width="4"/>
<circle cx="950" cy="250" r="120" fill="#0b1120"/>
<g clip-path="url(#zoom-clip)">
<!-- 背景网格 -->
<g stroke="#1e293b" stroke-width="1" stroke-dasharray="2 2">
<line x1="830" y1="250" x2="1070" y2="250" />
<line x1="950" y1="130" x2="950" y2="370" />
</g>
<!-- 硅胶唇边左/右 -->
<path id="zoom-lip-l" d="M 830,220 C 900,220 940,230 940,250 C 940,270 900,280 830,280 Z" fill="rgba(6, 182, 212, 0.2)" stroke="#06b6d4" stroke-width="2"/>
<path id="zoom-lip-r" d="M 1070,220 C 1000,220 960,230 960,250 C 960,270 1000,280 1070,280 Z" fill="rgba(6, 182, 212, 0.2)" stroke="#06b6d4" stroke-width="2"/>
<!-- 磁力线示意 -->
<g id="zoom-magnetic-waves" stroke="var(--accent-cyan)" stroke-dasharray="4 4" opacity="0.8">
<path d="M 942,240 Q 950,230 958,240" fill="none"/>
<path d="M 942,250 L 958,250" fill="none"/>
<path d="M 942,260 Q 950,270 958,260" fill="none"/>
</g>
<!-- 穿刺碳纤维臂剖面 -->
<rect id="zoom-arm" x="946" y="290" width="8" height="100" rx="4" fill="url(#carbon)" stroke="#94a3b8" stroke-width="2" opacity="0"/>
<circle id="zoom-arm-joint" cx="950" cy="340" r="3" fill="#f59e0b" opacity="0"/>
</g>
<!-- 放大镜UI边框装饰 -->
<path d="M 825,250 A 125 125 0 0 1 1075,250" fill="none" stroke="var(--accent-cyan)" stroke-width="2" stroke-dasharray="10 15"/>
<text x="950" y="115" text-anchor="middle" font-size="12" fill="var(--accent-cyan)" font-family="var(--font-title)">MICRO-CROSS-SECTION</text>
<text x="950" y="395" text-anchor="middle" font-size="12" fill="#94a3b8">磁性闭合力 / 8mm微间隙</text>
<!-- 连接线 -->
<path id="zoom-pointer" d="M 600,500 L 850,320" fill="none" stroke="#334155" stroke-width="1" stroke-dasharray="4 4"/>
<circle cx="850" cy="320" r="3" fill="var(--accent-cyan)"/>
</g>
</svg>
</main>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const CONFIG = {
centerX: 600,
baseY: 620,
targetY_min: 500, // 隐藏状态顶部高度
targetY_max: 150, // 展开状态顶部高度
stages: 4, // 剪叉级数
linkHalfLength: 90, // 单根连杆半长
};
// DOM 元素
const elements = {
scissorGroup: document.getElementById('scissor-group'),
shadeCloth: document.getElementById('shade-cloth'),
tractionBar: document.getElementById('traction-bar'),
blockL: document.getElementById('block-l'),
blockR: document.getElementById('block-r'),
motorRotor: document.getElementById('motor-rotor'),
progressPercent: document.getElementById('progress-percent'),
slider: document.getElementById('manual-slider'),
valForce: document.getElementById('val-force'),
statusText: document.getElementById('status-text'),
cardGap: document.getElementById('card-gap'),
puncturePoint: document.getElementById('puncture-point'),
zoomLipL: document.getElementById('zoom-lip-l'),
zoomLipR: document.getElementById('zoom-lip-r'),
zoomArm: document.getElementById('zoom-arm'),
zoomJoint: document.getElementById('zoom-arm-joint'),
zoomMagWaves: document.getElementById('zoom-magnetic-waves'),
zoomPointer: document.getElementById('zoom-pointer')
};
// 状态变量
let progress = 0; // 0 到 1
let isPlaying = true;
let direction = 1;
let animationFrameId = null;
let pauseTimeout = null;
// 初始化剪叉 SVG 结构
const links = [];
const joints = [];
function initSVG() {
// 每级有两个交叉杆: / 和 \
for (let i = 0; i < CONFIG.stages; i++) {
// /
const line1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line1.setAttribute('class', 'carbon-arm');
const inner1 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
inner1.setAttribute('class', 'carbon-arm-inner');
// \
const line2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
line2.setAttribute('class', 'carbon-arm');
const inner2 = document.createElementNS('http://www.w3.org/2000/svg', 'line');
inner2.setAttribute('class', 'carbon-arm-inner');
elements.scissorGroup.appendChild(line1);
elements.scissorGroup.appendChild(line2);
elements.scissorGroup.appendChild(inner1);
elements.scissorGroup.appendChild(inner2);
links.push({ out: line1, in: inner1, type: 'slash' });
links.push({ out: line2, in: inner2, type: 'backslash' });
// 中间铰链与两端铰链
const jointM = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
jointM.setAttribute('class', 'pivot-joint');
jointM.setAttribute('r', '4');
elements.scissorGroup.appendChild(jointM);
joints.push(jointM);
// 底部铰链 (仅在第一级和连接处需要)
const jointL = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
jointL.setAttribute('class', 'pivot-joint');
jointL.setAttribute('r', '4');
elements.scissorGroup.appendChild(jointL);
joints.push(jointL);
const jointR = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
jointR.setAttribute('class', 'pivot-joint');
jointR.setAttribute('r', '4');
elements.scissorGroup.appendChild(jointR);
joints.push(jointR);
}
}
// 渲染一帧
function render(p) {
// 1. 计算剪叉学参数
// p=0 时,高度 H_min = (baseY - targetY_min)
// p=1 时,高度 H_max = (baseY - targetY_max)
const currentY_top = CONFIG.targetY_min - p * (CONFIG.targetY_min - CONFIG.targetY_max);
const totalHeight = CONFIG.baseY - currentY_top;
// 每级的高度 2h = totalHeight / stages
const h = totalHeight / (2 * CONFIG.stages);
// 半宽 W = sqrt(L^2 - h^2)
const L = CONFIG.linkHalfLength;
const W = Math.sqrt(L * L - h * h);
const xl = CONFIG.centerX - W;
const xr = CONFIG.centerX + W;
// 2. 更新滑块位置
elements.blockL.setAttribute('x', xl - 15);
elements.blockR.setAttribute('x', xr - 15);
// 3. 更新电机旋转
const rot = p * 1440; // 旋转 4 圈
elements.motorRotor.setAttribute('transform', `rotate(${rot}, 350, 0)`);
// 4. 更新连杆与铰链
let jointIdx = 0;
for (let i = 0; i < CONFIG.stages; i++) {
const y_bottom = CONFIG.baseY - i * 2 * h;
const y_top = CONFIG.baseY - (i + 1) * 2 * h;
const y_mid = CONFIG.baseY - i * 2 * h - h;
const linkIdx = i * 2;
// / slash link: Left-Bottom to Right-Top
links[linkIdx].out.setAttribute('x1', xl); links[linkIdx].out.setAttribute('y1', y_bottom);
links[linkIdx].out.setAttribute('x2', xr); links[linkIdx].out.setAttribute('y2', y_top);
links[linkIdx].in.setAttribute('x1', xl); links[linkIdx].in.setAttribute('y1', y_bottom);
links[linkIdx].in.setAttribute('x2', xr); links[linkIdx].in.setAttribute('y2', y_top);
// \ backslash link: Right-Bottom to Left-Top
links[linkIdx+1].out.setAttribute('x1', xr); links[linkIdx+1].out.setAttribute('y1', y_bottom);
links[linkIdx+1].out.setAttribute('x2', xl); links[linkIdx+1].out.setAttribute('y2', y_top);
links[linkIdx+1].in.setAttribute('x1', xr); links[linkIdx+1].in.setAttribute('y1', y_bottom);
links[linkIdx+1].in.setAttribute('x2', xl); links[linkIdx+1].in.setAttribute('y2', y_top);
// Joints
joints[jointIdx].setAttribute('cx', CONFIG.centerX); joints[jointIdx].setAttribute('cy', y_mid); jointIdx++;
joints[jointIdx].setAttribute('cx', xl); joints[jointIdx].setAttribute('cy', y_bottom); jointIdx++;
joints[jointIdx].setAttribute('cx', xr); joints[jointIdx].setAttribute('cy', y_bottom); jointIdx++;
}
// 5. 更新顶部牵引杆与遮阳帘形状 (受平行四边形车窗约束)
// 车窗左边缘: 250,500 到 350,150 -> dx/dy = 100 / -350
// 车窗右边缘: 950,500 到 850,150 -> dx/dy = -100 / -350
const dy = currentY_top - 500;
const leftX = 250 + dy * (100 / -350);
const rightX = 950 + dy * (-100 / -350);
elements.tractionBar.setAttribute('y1', currentY_top);
elements.tractionBar.setAttribute('y2', currentY_top);
elements.tractionBar.setAttribute('x1', leftX);
elements.tractionBar.setAttribute('x2', rightX);
elements.shadeCloth.setAttribute('points', `250,500 950,500 ${rightX},${currentY_top} ${leftX},${currentY_top}`);
// 6. 更新 IFR 核心表现 (唇边突破与闭合)
updateMicroSection(p, currentY_top);
// 7. 更新UI百分比
elements.progressPercent.textContent = `${(p * 100).toFixed(0)}%`;
elements.slider.value = p * 100;
}
function updateMicroSection(p, y_top) {
// 缝隙磁力计算
// 当剪叉最顶部 y_top < 500 且 仍在伸出过程中,说明机械臂正穿过缝隙。
// 实际上由于是 X 型交叉,中心点(600)始终有一根碳纤维杆在上下滑动。
// 只要 p > 0.02,臂就穿过了缝隙。
const isPenetrating = p > 0.05;
if (isPenetrating) {
// 吸力受阻,微观打开
elements.zoomLipL.setAttribute('d', 'M 830,220 C 900,220 934,230 934,250 C 934,270 900,280 830,280 Z');
elements.zoomLipR.setAttribute('d', 'M 1070,220 C 1000,220 966,230 966,250 C 966,270 1000,280 1070,280 Z');
elements.zoomMagWaves.style.opacity = '0.2';
elements.zoomMagWaves.setAttribute('stroke', '#ef4444'); // 磁力波变红减弱
// 碳纤维臂出现
elements.zoomArm.style.opacity = '1';
elements.zoomJoint.style.opacity = '1';
// 将手臂的移动映射到局部放大区
// 用一个相对运动模拟
const localY = 250 + ((p * 1000) % 60) - 30;
elements.zoomArm.setAttribute('y', localY - 50);
elements.zoomJoint.setAttribute('cy', localY);
// HUD 状态更新
elements.valForce.textContent = '1.5';
elements.valForce.className = 'hud-value';
elements.statusText.textContent = '极薄穿透 (两侧吸合)';
elements.statusText.style.color = 'var(--accent-cyan)';
elements.cardGap.classList.remove('alert');
// 主视图穿刺点发光
elements.puncturePoint.setAttribute('r', 12 + Math.sin(p * 20) * 4);
elements.puncturePoint.style.opacity = '1';
// 连线指向穿刺点
elements.zoomPointer.setAttribute('d', 'M 600,500 L 850,320');
} else {
// 完全闭合
elements.zoomLipL.setAttribute('d', 'M 830,220 C 900,220 940,230 940,250 C 940,270 900,280 830,280 Z');
elements.zoomLipR.setAttribute('d', 'M 1070,220 C 1000,220 960,230 960,250 C 960,270 1000,280 1070,280 Z');
elements.zoomMagWaves.style.opacity = '0.8';
elements.zoomMagWaves.setAttribute('stroke', 'var(--accent-cyan)');
elements.zoomArm.style.opacity = '0';
elements.zoomJoint.style.opacity = '0';
elements.valForce.textContent = '2.0';
elements.valForce.className = 'hud-value amber';
elements.statusText.textContent = '瞬间自动闭合 (无缝)';
elements.statusText.style.color = 'var(--accent-amber)';
elements.cardGap.classList.add('alert');
elements.puncturePoint.style.opacity = '0';
elements.zoomPointer.setAttribute('d', 'M 600,500 L 850,320'); // 虚线连接
}
}
// 动画循环
let lastTime = 0;
const SPEED = 0.0003; // 动画速度
function animate(time) {
if (!lastTime) lastTime = time;
const deltaTime = time - lastTime;
lastTime = time;
if (isPlaying) {
if (direction === 1) {
progress += SPEED * deltaTime;
if (progress >= 1) {
progress = 1;
direction = -1;
isPlaying = false;
setTimeout(() => { isPlaying = true; }, 2000); // 顶部停留 2 秒
}
} else {
progress -= SPEED * deltaTime;
if (progress <= 0) {
progress = 0;
direction = 1;
isPlaying = false;
setTimeout(() => { isPlaying = true; }, 2000); // 底部停留 2 秒
}
}
render(progress);
}
animationFrameId = requestAnimationFrame(animate);
}
// 交互控制
elements.slider.addEventListener('input', (e) => {
isPlaying = false;
progress = e.target.value / 100;
render(progress);
clearTimeout(pauseTimeout);
});
elements.slider.addEventListener('change', () => {
// 释放后 2 秒恢复自动播放
clearTimeout(pauseTimeout);
pauseTimeout = setTimeout(() => {
lastTime = 0; // 重置计时器防止跳变
isPlaying = true;
// 确定运动方向
direction = progress >= 0.5 ? -1 : 1;
}, 2000);
});
// 启动初始化
initSVG();
render(0);
// 满足 "重开即播 / 加载后自动播放" 需求
animationFrameId = requestAnimationFrame(animate);
});
</script>
</body>
</html>
积分规则:第一轮对话扣减8分,后续每轮扣6分
等待动画代码生成...
