独立渲染引擎就绪引擎就绪
<!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-color: #060913;
--panel-bg: rgba(13, 20, 36, 0.7);
--border-color: rgba(0, 240, 255, 0.2);
--text-main: #e2e8f0;
--text-muted: #64748b;
--energy-color: #00f0ff;
--kinetic-color: #ff5500;
--signal-color: #10b981;
/* Dynamic variables controlled by JS */
--flow-speed: 2s;
--energy-opacity: 0.5;
--charge-level: 50%;
--charge-color: #10b981;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-image:
radial-gradient(circle at 50% 50%, #0d1627 0%, #03050a 100%),
linear-gradient(rgba(0, 240, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(0, 240, 255, 0.03) 1px, transparent 1px);
background-size: 100% 100%, 40px 40px, 40px 40px;
}
/* 绝对定位的 UI 层,严格控制尺寸和位置,不遮挡核心动画 */
.overlay-panel {
position: absolute;
background: var(--panel-bg);
backdrop-filter: blur(10px);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 12px 16px;
z-index: 10;
}
.top-left {
top: 24px;
left: 24px;
}
.top-right {
top: 24px;
right: 24px;
text-align: right;
}
.bottom-center {
bottom: 32px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 16px;
padding: 16px 24px;
}
h1 {
font-size: 14px;
font-weight: 600;
letter-spacing: 1px;
color: var(--energy-color);
margin-bottom: 4px;
}
p, .param-text {
font-size: 12px;
color: var(--text-muted);
line-height: 1.4;
}
.param-value {
color: var(--text-main);
font-family: monospace;
font-size: 13px;
}
/* 交互滑块样式 */
.slider-container {
display: flex;
flex-direction: column;
gap: 6px;
min-width: 200px;
}
.slider-header {
display: flex;
justify-content: space-between;
font-size: 12px;
color: var(--text-muted);
}
input[type=range] {
-webkit-appearance: none;
width: 100%;
background: transparent;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: rgba(255, 255, 255, 0.1);
border-radius: 2px;
}
input[type=range]::-webkit-slider-thumb {
height: 16px;
width: 16px;
border-radius: 50%;
background: var(--kinetic-color);
cursor: pointer;
-webkit-appearance: none;
margin-top: -6px;
box-shadow: 0 0 10px var(--kinetic-color);
transition: transform 0.1s;
}
input[type=range]::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
/* 核心动画容器 */
.svg-container {
width: 100%;
max-width: 1200px;
height: 100%;
max-height: 800px;
display: flex;
justify-content: center;
align-items: center;
padding: 40px;
}
svg {
width: 100%;
height: 100%;
overflow: visible;
}
/* CSS 动画类 */
.flow-line {
stroke-dasharray: 8 8;
animation: flow var(--flow-speed) linear infinite;
opacity: var(--energy-opacity);
transition: opacity 0.3s;
}
@keyframes flow {
to { stroke-dashoffset: -16; }
}
.signal-arc {
opacity: 0;
transform-origin: 820px 320px;
}
@keyframes radiate {
0% { transform: scale(0.8); opacity: 0; }
50% { opacity: var(--energy-opacity); }
100% { transform: scale(1.8); opacity: 0; }
}
</style>
</head>
<body>
<!-- 顶部左侧:标题与机理说明 -->
<div class="overlay-panel top-left">
<h1>无源物联网:压电振动能量采集系统</h1>
<p>通过悬臂梁放大筛箱振动,压电陶瓷形变产生电能<br>彻底消除外部供电依赖 (IFR)</p>
</div>
<!-- 顶部右侧:关键参数与状态 -->
<div class="overlay-panel top-right">
<p>设计功率输出: <span class="param-value">0.5~2W</span></p>
<p>超级电容储能: <span class="param-value">100F/2.7V</span></p>
<div style="margin-top: 8px; border-top: 1px solid var(--border-color); padding-top: 8px;">
<p>实时采集效率: <span class="param-value" id="val-efficiency" style="color: var(--energy-color);">0%</span></p>
<p>储能状态: <span class="param-value" id="val-storage" style="color: var(--charge-color);">0%</span></p>
</div>
</div>
<!-- 底部控制:交互引导 -->
<div class="overlay-panel bottom-center">
<div class="slider-container">
<div class="slider-header">
<span>环境振动幅值控制</span>
<span id="val-vibration" style="color: var(--kinetic-color); font-family: monospace;">极低</span>
</div>
<input type="range" id="vibration-slider" min="0" max="100" value="50">
</div>
<p style="max-width: 200px; font-size: 11px; margin-left: 12px; border-left: 1px solid rgba(255,255,255,0.1); padding-left: 12px;">
调节环境振动幅度<br>观察压电能量转换及储能缓冲机制
</p>
</div>
<!-- 核心可视化区域 -->
<div class="svg-container">
<svg viewBox="0 0 1000 600" preserveAspectRatio="xMidYMid meet">
<defs>
<!-- 发光滤镜 -->
<filter id="glow-cyan" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-orange" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="6" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- 渐变定义 -->
<linearGradient id="metal-grad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#334155" />
<stop offset="50%" stop-color="#475569" />
<stop offset="100%" stop-color="#1e293b" />
</linearGradient>
<linearGradient id="piezo-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#0284c7" />
<stop offset="100%" stop-color="#00f0ff" />
</linearGradient>
<linearGradient id="module-bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="rgba(30, 41, 59, 0.8)" />
<stop offset="100%" stop-color="rgba(15, 23, 42, 0.8)" />
</linearGradient>
</defs>
<!-- 背景装饰线 -->
<path d="M 150 450 L 850 450" stroke="rgba(255,255,255,0.05)" stroke-width="2" stroke-dasharray="10 5" />
<!-- 动态接线 (由JS更新路径) -->
<path id="wire-dynamic" d="M 280 300 C 350 300, 400 240, 500 240" fill="none" stroke="#00f0ff" stroke-width="2" class="flow-line" filter="url(#glow-cyan)" />
<path d="M 620 240 L 740 240" fill="none" stroke="#00f0ff" stroke-width="2" class="flow-line" filter="url(#glow-cyan)" />
<path d="M 800 290 L 800 370" fill="none" stroke="#00f0ff" stroke-width="2" class="flow-line" filter="url(#glow-cyan)" />
<!-- === 物理振动系统 === -->
<g id="vibration-system">
<!-- 振动源基座 (筛箱) -->
<rect x="80" y="220" width="100" height="160" rx="8" fill="url(#metal-grad)" stroke="#64748b" stroke-width="2" />
<circle cx="130" cy="300" r="12" fill="#0f172a" stroke="#475569" stroke-width="3" />
<text x="130" y="405" fill="var(--text-muted)" font-size="12" text-anchor="middle">振动体(筛箱)</text>
<!-- 能量波纹(表示动能) -->
<g id="kinetic-waves" filter="url(#glow-orange)" opacity="0.5">
<path d="M 50 250 Q 30 300 50 350" fill="none" stroke="var(--kinetic-color)" stroke-width="2" />
<path d="M 30 230 Q 0 300 30 370" fill="none" stroke="var(--kinetic-color)" stroke-width="2" />
</g>
<!-- 悬臂梁与压电组件 (绕支点旋转) -->
<g id="cantilever-assembly">
<!-- 主梁 -->
<rect x="130" y="292" width="220" height="16" fill="#94a3b8" />
<!-- 压电陶瓷片 (上下各一) -->
<rect id="piezo-top" x="160" y="284" width="100" height="8" rx="2" fill="url(#piezo-grad)" filter="url(#glow-cyan)" />
<rect id="piezo-bottom" x="160" y="308" width="100" height="8" rx="2" fill="url(#piezo-grad)" filter="url(#glow-cyan)" />
<text x="210" y="275" fill="#00f0ff" font-size="11" text-anchor="middle" filter="url(#glow-cyan)">压电能量采集器</text>
<!-- 质量块 -->
<circle cx="350" cy="300" r="24" fill="url(#metal-grad)" stroke="#cbd5e1" stroke-width="2" />
<circle cx="350" cy="300" r="8" fill="#475569" />
<text x="350" y="340" fill="var(--text-muted)" font-size="11" text-anchor="middle">质量块放大</text>
</g>
</g>
<!-- === 固定电路模块 === -->
<!-- 1. 整流/DCDC 管理模块 -->
<g transform="translate(480, 190)">
<rect x="0" y="0" width="140" height="100" rx="12" fill="url(#module-bg)" stroke="var(--border-color)" stroke-width="1.5" />
<path d="M 20 50 L 40 30 L 70 70 L 90 30 L 120 50" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" opacity="0.5"/>
<!-- 动态整流指示 -->
<path d="M 20 50 L 40 30 L 70 70 L 90 30 L 120 50" fill="none" stroke="#00f0ff" stroke-width="2" stroke-linejoin="round" class="flow-line" filter="url(#glow-cyan)" />
<text x="70" y="125" fill="var(--text-muted)" font-size="12" text-anchor="middle">整流与DCDC稳压</text>
</g>
<!-- 2. 超级电容储能模块 -->
<g transform="translate(740, 150)">
<rect x="0" y="0" width="120" height="140" rx="12" fill="url(#module-bg)" stroke="var(--border-color)" stroke-width="1.5" />
<!-- 电池外壳 -->
<rect x="35" y="20" width="50" height="90" rx="4" fill="none" stroke="#475569" stroke-width="2" />
<rect x="50" y="12" width="20" height="8" rx="2" fill="#475569" />
<!-- 动态电量填充 -->
<rect id="charge-fill" x="37" y="108" width="46" height="0" rx="2" fill="var(--charge-color)" style="transition: height 0.3s, y 0.3s, fill 0.5s;" />
<!-- 电量网格线 -->
<line x1="35" y1="42.5" x2="85" y2="42.5" stroke="#1e293b" stroke-width="2" />
<line x1="35" y1="65" x2="85" y2="65" stroke="#1e293b" stroke-width="2" />
<line x1="35" y1="87.5" x2="85" y2="87.5" stroke="#1e293b" stroke-width="2" />
<text x="60" y="135" fill="var(--text-main)" font-size="11" text-anchor="middle" font-family="monospace">100F/2.7V</text>
<text x="60" y="165" fill="var(--text-muted)" font-size="12" text-anchor="middle">超级电容缓冲</text>
</g>
<!-- 3. 无线传感节点 (LoRa/WiFi) -->
<g transform="translate(720, 370)">
<rect x="0" y="0" width="160" height="80" rx="12" fill="url(#module-bg)" stroke="var(--border-color)" stroke-width="1.5" />
<circle cx="40" cy="40" r="15" fill="#0f172a" stroke="#94a3b8" stroke-width="2" />
<circle id="sensor-indicator" cx="40" cy="40" r="6" fill="#10b981" />
<!-- 天线 -->
<path d="M 100 20 L 100 -20" fill="none" stroke="#94a3b8" stroke-width="3" stroke-linecap="round" />
<circle cx="100" cy="-20" r="4" fill="#10b981" />
<text x="40" y="70" fill="var(--text-muted)" font-size="10" text-anchor="middle">液位/应变</text>
<text x="100" y="60" fill="var(--text-main)" font-size="13" text-anchor="middle">无线传输节点</text>
<!-- 无线信号波纹 -->
<g id="signal-waves" stroke="#10b981" fill="none" stroke-width="2" stroke-linecap="round">
<path class="signal-arc" d="M 120 -40 Q 140 -20 120 0" style="animation: radiate 2s infinite 0s;" />
<path class="signal-arc" d="M 135 -55 Q 165 -20 135 15" style="animation: radiate 2s infinite 0.66s;" />
<path class="signal-arc" d="M 150 -70 Q 190 -20 150 30" style="animation: radiate 2s infinite 1.33s;" />
</g>
</g>
<!-- 连接指示点 -->
<circle cx="500" cy="240" r="4" fill="#00f0ff" filter="url(#glow-cyan)" />
<circle cx="620" cy="240" r="4" fill="#00f0ff" filter="url(#glow-cyan)" />
<circle cx="740" cy="240" r="4" fill="#00f0ff" filter="url(#glow-cyan)" />
<circle cx="800" cy="290" r="4" fill="#00f0ff" filter="url(#glow-cyan)" />
<circle cx="800" cy="370" r="4" fill="#00f0ff" filter="url(#glow-cyan)" />
</svg>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const root = document.documentElement;
const slider = document.getElementById('vibration-slider');
// DOM 元素引用
const baseElement = document.getElementById('vibration-system');
const cantilever = document.getElementById('cantilever-assembly');
const dynamicWire = document.getElementById('wire-dynamic');
const piezoTop = document.getElementById('piezo-top');
const piezoBottom = document.getElementById('piezo-bottom');
const chargeFill = document.getElementById('charge-fill');
const sensorInd = document.getElementById('sensor-indicator');
const signalArcs = document.querySelectorAll('.signal-arc');
const valVib = document.getElementById('val-vibration');
const valEff = document.getElementById('val-efficiency');
const valStore = document.getElementById('val-storage');
const kineticWaves = document.getElementById('kinetic-waves');
// 物理仿真状态
let time = 0;
let currentAmp = 0.5; // 当前振幅 (0-1)
let targetAmp = 0.5; // 目标振幅 (0-1)
let chargeLevel = 20; // 当前电量 (0-100)
// 动画主循环
function animate() {
// 1. 平滑插值振幅 (用户交互响应)
targetAmp = slider.value / 100;
currentAmp += (targetAmp - currentAmp) * 0.05;
// 更新界面文本
if (targetAmp < 0.2) valVib.textContent = '微弱';
else if (targetAmp < 0.6) valVib.textContent = '中等';
else valVib.textContent = '剧烈';
// 2. 物理运动计算
// 基座垂直简谐振动
const baseMaxY = 20;
const baseY = Math.sin(time) * currentAmp * baseMaxY;
// 悬臂梁弯曲 (因质量块惯性产生相位滞后和角度变形)
const beamMaxAngle = 12;
const beamAngle = Math.sin(time - Math.PI / 3) * currentAmp * beamMaxAngle;
// 应用变换
baseElement.setAttribute('transform', `translate(0, ${baseY})`);
// 绕左侧支撑点 (x=130, y=300) 旋转
cantilever.setAttribute('transform', `rotate(${beamAngle}, 130, 300)`);
// 3. 动态接线更新 (起点随基座运动,终点固定在整流器)
// 起点位于压电片引出端:近似计算其随基座和梁的绝对坐标,简化起见绑定在基座上即可
const wireStartX = 280;
const wireStartY = 300 + baseY;
dynamicWire.setAttribute('d', `M ${wireStartX} ${wireStartY} C 350 ${wireStartY}, 400 240, 500 240`);
// 4. 发电视觉反馈
// 压电片亮度随形变(角度)变化
const stress = Math.abs(beamAngle) / beamMaxAngle;
const activeOpacity = 0.3 + (stress * 0.7);
piezoTop.style.opacity = activeOpacity;
piezoBottom.style.opacity = activeOpacity;
kineticWaves.style.opacity = currentAmp * 0.8;
// 更新 CSS 变量驱动能量流
const energyFlow = Math.max(0, (currentAmp - 0.1) * 1.1); // 存在死区,振幅极小不发电
root.style.setProperty('--energy-opacity', energyFlow.toFixed(2));
root.style.setProperty('--flow-speed', (3 - currentAmp * 2) + 's');
valEff.textContent = (energyFlow * 100).toFixed(0) + '%';
// 5. 储能系统逻辑 (充放电平衡)
// 发电量与消耗量抗衡
const generateRate = energyFlow * 0.3;
const consumeRate = chargeLevel > 10 ? 0.1 : 0; // 如果有电则消耗
chargeLevel += (generateRate - consumeRate);
chargeLevel = Math.max(0, Math.min(100, chargeLevel)); // 限制在 0-100
// 更新电量 UI
const height = (chargeLevel / 100) * 88;
const yPos = 108 - height;
chargeFill.setAttribute('height', height);
chargeFill.setAttribute('y', yPos);
valStore.textContent = chargeLevel.toFixed(1) + '%';
// 电量颜色映射 (低电量红,正常绿)
let capColor = '#10b981'; // 绿
if (chargeLevel < 20) capColor = '#ef4444'; // 红
else if (chargeLevel < 50) capColor = '#f59e0b'; // 黄
root.style.setProperty('--charge-color', capColor);
sensorInd.setAttribute('fill', chargeLevel > 10 ? capColor : '#475569');
// 6. 无线传输控制
if (chargeLevel > 10) {
signalArcs.forEach(arc => {
arc.style.animationPlayState = 'running';
arc.style.stroke = capColor;
});
} else {
signalArcs.forEach(arc => arc.style.animationPlayState = 'paused');
}
// 步进时间 (频率随振幅微调,更真实)
time += 0.15 + (currentAmp * 0.1);
requestAnimationFrame(animate);
}
// 启动动画循环
animate();
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
