独立渲染引擎就绪引擎就绪
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>5G 无人化值守与远程监控系统原理</title>
<style>
/* =========================================
AESTHETICS & TYPOGRAPHY
Cyber-industrial / Tech-minimalist theme
========================================= */
@import url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400;500;600&family=Noto+Sans+SC:wght@300;400;500&display=swap');
:root {
--bg-base: #060913;
--grid-color: rgba(0, 243, 255, 0.05);
--neon-cyan: #00f3ff;
--neon-cyan-dim: rgba(0, 243, 255, 0.3);
--neon-purple: #8a2be2;
--neon-alert: #ff2a6d;
--text-main: #a0aec0;
--text-bright: #ffffff;
--panel-bg: rgba(6, 9, 19, 0.7);
--panel-border: rgba(0, 243, 255, 0.15);
}
body, html {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
background-color: var(--bg-base);
font-family: 'Noto Sans SC', sans-serif;
color: var(--text-main);
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
/* Background Grid Overlay */
.bg-grid {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 40px 40px;
z-index: 0;
pointer-events: none;
}
/* Radial gradient for depth */
.bg-glow {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 80vw; height: 80vh;
background: radial-gradient(circle, rgba(0, 243, 255, 0.03) 0%, rgba(6, 9, 19, 0) 70%);
z-index: 0;
pointer-events: none;
}
/* =========================================
UI PANELS (Strictly positioned in corners, small text)
========================================= */
.ui-panel {
position: absolute;
background: var(--panel-bg);
border: 1px solid var(--panel-border);
border-radius: 6px;
padding: 12px 16px;
backdrop-filter: blur(10px);
z-index: 10;
font-size: 12px;
pointer-events: none;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
}
.ui-top-left { top: 24px; left: 24px; max-width: 250px; }
.ui-bottom-left { bottom: 24px; left: 24px; }
.ui-top-right { top: 24px; right: 24px; pointer-events: auto; }
.ui-bottom-right { bottom: 24px; right: 24px; }
h1, h2, .font-tech {
font-family: 'Chakra Petch', sans-serif;
margin: 0 0 8px 0;
}
h1 {
color: var(--neon-cyan);
font-size: 14px;
font-weight: 600;
letter-spacing: 1px;
text-transform: uppercase;
border-bottom: 1px solid var(--neon-cyan-dim);
padding-bottom: 4px;
}
.data-row {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
align-items: center;
}
.data-label { color: #6b7280; }
.data-value {
color: var(--text-bright);
font-family: 'Chakra Petch', sans-serif;
font-weight: 500;
}
.highlight { color: var(--neon-cyan); }
.alert-text { color: var(--neon-alert); }
/* Status Indicator */
.status-dot {
display: inline-block;
width: 6px; height: 6px;
border-radius: 50%;
background-color: var(--neon-cyan);
box-shadow: 0 0 8px var(--neon-cyan);
margin-right: 6px;
animation: pulse-dot 2s infinite;
}
@keyframes pulse-dot {
0% { opacity: 0.5; box-shadow: 0 0 4px var(--neon-cyan); }
50% { opacity: 1; box-shadow: 0 0 12px var(--neon-cyan); }
100% { opacity: 0.5; box-shadow: 0 0 4px var(--neon-cyan); }
}
/* Interactive Controls */
.btn {
background: transparent;
border: 1px solid var(--neon-cyan-dim);
color: var(--neon-cyan);
padding: 6px 12px;
border-radius: 4px;
font-family: 'Noto Sans SC', sans-serif;
font-size: 12px;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 8px;
display: block;
width: 100%;
text-align: center;
}
.btn:hover {
background: rgba(0, 243, 255, 0.1);
border-color: var(--neon-cyan);
box-shadow: 0 0 10px rgba(0, 243, 255, 0.2);
}
.btn-alert {
color: var(--neon-alert);
border-color: rgba(255, 42, 109, 0.3);
}
.btn-alert:hover, .btn-alert.active {
background: rgba(255, 42, 109, 0.1);
border-color: var(--neon-alert);
box-shadow: 0 0 10px rgba(255, 42, 109, 0.2);
}
/* =========================================
MAIN SVG CONTAINER
Takes up maximum space, core visual element
========================================= */
#animation-container {
position: relative;
width: 100%;
height: 100%;
z-index: 5;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 90%;
height: 90%;
max-width: 1400px;
max-height: 800px;
filter: drop-shadow(0 0 20px rgba(0,0,0,0.5));
}
/* SVG Element Styles */
.node-base { fill: #0f172a; stroke: var(--neon-cyan-dim); stroke-width: 1.5; }
.text-svg { font-family: 'Noto Sans SC', sans-serif; font-size: 14px; fill: var(--text-main); text-anchor: middle; }
.text-svg-title { font-size: 16px; fill: var(--text-bright); font-weight: 500; }
.text-svg-tech { font-family: 'Chakra Petch', sans-serif; font-size: 12px; fill: var(--neon-cyan); }
.path-main { fill: none; stroke: var(--panel-border); stroke-width: 2; stroke-dasharray: 4 4; }
.path-glow { fill: none; stroke: var(--neon-cyan); stroke-width: 4; opacity: 0.1; filter: url(#glow); }
.path-vpn { fill: none; stroke: var(--neon-purple); stroke-width: 12; opacity: 0.15; stroke-linecap: round; }
/* CSS Animations applied to SVG elements */
.spin-slow { transform-origin: center; animation: spin 20s linear infinite; }
.spin-slow-reverse { transform-origin: center; animation: spin-reverse 25s linear infinite; }
@keyframes spin { 100% { transform: rotate(360deg); } }
@keyframes spin-reverse { 100% { transform: rotate(-360deg); } }
/* Dynamic classes controlled by JS */
.state-alert .path-glow { stroke: var(--neon-alert); opacity: 0.2; }
.state-alert .text-svg-tech.opc-mqtt { fill: var(--neon-alert); }
.state-alert .node-gateway { stroke: var(--neon-alert); }
</style>
</head>
<body>
<!-- Background Effects -->
<div class="bg-grid"></div>
<div class="bg-glow"></div>
<!-- UI Overlay Panels -->
<div class="ui-panel ui-top-left">
<h1>最终理想解 (IFR) 架构</h1>
<div style="color: #6b7280; line-height: 1.5;">
利用 5G 网关作为透明代理枢纽,无缝桥接物理设备与云端,消除空间距离障碍,实现“数据即刻可见,指令即刻触达”的理想无人化状态。
</div>
</div>
<div class="ui-panel ui-bottom-left">
<div class="font-tech" style="color: var(--neon-cyan); margin-bottom: 8px;">SYSTEM PARAMS //</div>
<div class="data-row">
<span class="data-label">上传频率 (MQTT):</span>
<span class="data-value highlight">2 秒/次</span>
</div>
<div class="data-row">
<span class="data-label">底层采集 (OPC UA):</span>
<span class="data-value">实时加密</span>
</div>
<div class="data-row">
<span class="data-label">安全防护机制:</span>
<span class="data-value" style="color: var(--neon-purple);">VPN 隧道</span>
</div>
</div>
<div class="ui-panel ui-bottom-right">
<div class="font-tech" style="color: var(--neon-cyan); margin-bottom: 8px;">LINK STATUS //</div>
<div class="data-row">
<span class="data-label">控制指令时延:</span>
<span class="data-value highlight" id="latency-val">42 ms</span>
</div>
<div class="data-row">
<span class="data-label">网络状态 (5G):</span>
<span class="data-value"><span class="status-dot"></span>已连接</span>
</div>
</div>
<div class="ui-panel ui-top-right">
<div class="font-tech" style="color: #6b7280; margin-bottom: 8px;">INTERACTIVE SIMULATION</div>
<button class="btn" id="btn-control">模拟远程下发指令 (⬇)</button>
<button class="btn btn-alert" id="btn-alarm">触发井场异常报警 (⬆)</button>
</div>
<!-- Main Animation SVG -->
<div id="animation-container">
<!-- viewBox centered, ample space -->
<svg viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" id="main-canvas">
<defs>
<!-- Filters -->
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="8" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<filter id="glow-strong" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="12" result="blur" />
<feComposite in="SourceGraphic" in2="blur" operator="over" />
</filter>
<!-- Gradients -->
<linearGradient id="grad-cyan" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00f3ff" stop-opacity="0.8" />
<stop offset="100%" stop-color="#0055ff" stop-opacity="0.2" />
</linearGradient>
<linearGradient id="grad-vpn" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#8a2be2" stop-opacity="0.1" />
<stop offset="50%" stop-color="#8a2be2" stop-opacity="0.4" />
<stop offset="100%" stop-color="#8a2be2" stop-opacity="0.1" />
</linearGradient>
<!-- Data Packet Symbols -->
<g id="packet-up">
<circle cx="0" cy="0" r="4" fill="#00f3ff" filter="url(#glow)" />
<circle cx="0" cy="0" r="2" fill="#fff" />
</g>
<g id="packet-alarm">
<circle cx="0" cy="0" r="5" fill="#ff2a6d" filter="url(#glow-strong)" />
<circle cx="0" cy="0" r="2" fill="#fff" />
</g>
<g id="packet-down">
<rect x="-6" y="-3" width="12" height="6" rx="2" fill="#00f3ff" filter="url(#glow)" />
</g>
<!-- Network Waves Symbol -->
<g id="radio-waves">
<circle cx="0" cy="0" r="10" fill="none" stroke="#00f3ff" stroke-width="1.5" opacity="0">
<animate attributeName="r" values="10; 40" dur="2s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.8; 0" dur="2s" repeatCount="indefinite" />
</circle>
<circle cx="0" cy="0" r="10" fill="none" stroke="#00f3ff" stroke-width="1.5" opacity="0">
<animate attributeName="r" values="10; 40" dur="2s" begin="1s" repeatCount="indefinite" />
<animate attributeName="opacity" values="0.8; 0" dur="2s" begin="1s" repeatCount="indefinite" />
</circle>
</g>
</defs>
<!-- ============================== PATHS ============================== -->
<!-- Base Path 1: PLC to Gateway -->
<path id="path-plc-gw" d="M 350 450 L 600 450" class="path-main" />
<path d="M 350 450 L 600 450" class="path-glow" />
<!-- Base Path 2: Gateway to Cloud -->
<path id="path-gw-cloud" d="M 1000 450 C 1150 450 1200 300 1350 300" class="path-main" />
<path d="M 1000 450 C 1150 450 1200 300 1350 300" class="path-glow" />
<!-- VPN Tunnel visualization (Gateway to Cloud) -->
<path d="M 1000 450 C 1150 450 1200 300 1350 300" class="path-vpn" />
<text x="1150" y="360" class="text-svg-tech" style="fill: var(--neon-purple); opacity: 0.7;">加密 VPN 隧道</text>
<!-- Base Path 3: Gateway to APP -->
<path id="path-gw-app" d="M 1000 450 C 1150 450 1200 600 1350 600" class="path-main" />
<path d="M 1000 450 C 1150 450 1200 600 1350 600" class="path-glow" />
<!-- Control Return Path (Cloud to PLC via GW) -->
<path id="path-return" d="M 1350 300 C 1200 300 1150 450 1000 450 L 350 450" fill="none" />
<!-- ============================== NODES ============================== -->
<!-- NODE 1: Wellsite / PLC (Left) -->
<g transform="translate(200, 450)">
<!-- Decorative tech circles -->
<circle cx="0" cy="0" r="80" fill="none" stroke="rgba(0,243,255,0.1)" stroke-width="1" class="spin-slow" stroke-dasharray="10 5" />
<circle cx="0" cy="0" r="95" fill="none" stroke="rgba(0,243,255,0.05)" stroke-width="1" class="spin-slow-reverse" stroke-dasharray="20 10 5 10" />
<!-- Main Box -->
<rect x="-60" y="-70" width="120" height="140" rx="8" class="node-base" />
<rect x="-50" y="-60" width="100" height="40" rx="4" fill="#1e293b" stroke="#334155" />
<!-- PLC lights -->
<circle cx="-30" cy="-40" r="4" fill="#00ff00" filter="url(#glow)" />
<circle cx="-15" cy="-40" r="4" fill="#00ff00" />
<circle cx="0" cy="-40" r="4" fill="#00ff00" />
<circle cx="15" cy="-40" r="4" fill="#334155" id="plc-alarm-light" />
<!-- Data bars simulation -->
<rect x="-40" y="-5" width="6" height="20" fill="var(--neon-cyan)" opacity="0.6">
<animate attributeName="height" values="20; 5; 25; 15; 20" dur="1.5s" repeatCount="indefinite" />
<animate attributeName="y" values="-5; 10; -10; 0; -5" dur="1.5s" repeatCount="indefinite" />
</rect>
<rect x="-25" y="-5" width="6" height="30" fill="var(--neon-cyan)" opacity="0.4">
<animate attributeName="height" values="30; 10; 20; 5; 30" dur="2.1s" repeatCount="indefinite" />
<animate attributeName="y" values="-5; 15; 5; 20; -5" dur="2.1s" repeatCount="indefinite" />
</rect>
<text x="0" y="90" class="text-svg-title">井场前端采集系统</text>
<text x="0" y="110" class="text-svg">PLC / 传感器 / 阀门</text>
<!-- Real-time data generating visual -->
<text x="0" y="40" class="text-svg-tech" opacity="0.8">液位: 68%</text>
<text x="0" y="55" class="text-svg-tech" opacity="0.8">伺服电流: 4.2A</text>
</g>
<!-- NODE 2: 5G Industrial Gateway (Center) -->
<g transform="translate(800, 450)" class="node-gateway">
<!-- Large Hexagon base representing the core innovation/hub -->
<polygon points="0,-100 86.6,-50 86.6,50 0,100 -86.6,50 -86.6,-50" fill="url(#grad-cyan)" opacity="0.1" />
<polygon points="0,-110 95.2,-55 95.2,55 0,110 -95.2,55 -95.2,-55" fill="none" stroke="var(--neon-cyan)" stroke-width="1" opacity="0.3" class="spin-slow" />
<!-- Gateway Box -->
<rect x="-50" y="-40" width="100" height="80" rx="10" fill="#0f172a" stroke="var(--neon-cyan)" stroke-width="2" filter="url(#glow)" />
<path d="M -30 -10 L -10 -10 L 0 10 L 20 -10 L 30 -10" fill="none" stroke="#fff" stroke-width="2" opacity="0.5" />
<!-- Antennas -->
<line x1="-30" y1="-40" x2="-40" y2="-70" stroke="var(--neon-cyan)" stroke-width="3" stroke-linecap="round" />
<line x1="30" y1="-40" x2="40" y2="-70" stroke="var(--neon-cyan)" stroke-width="3" stroke-linecap="round" />
<!-- 5G Waves coming from antennas -->
<use href="#radio-waves" x="-40" y="-70" />
<use href="#radio-waves" x="40" y="-70" />
<text x="0" y="140" class="text-svg-title">工业 5G 网关</text>
<text x="0" y="160" class="text-svg">边缘计算与协议转换</text>
<!-- Protocol translation visual (The core IFR mechanism) -->
<!-- OPC UA IN -->
<path d="M -200 0 L -100 0" fill="none" stroke="var(--neon-cyan-dim)" stroke-width="1" stroke-dasharray="2 2" />
<text x="-150" y="-10" class="text-svg-tech opc-mqtt">OPC UA 数据模型 (局域)</text>
<!-- MQTT OUT -->
<path d="M 100 0 L 200 0" fill="none" stroke="var(--neon-cyan-dim)" stroke-width="1" stroke-dasharray="2 2" />
<text x="150" y="-10" class="text-svg-tech opc-mqtt">MQTT 物联网协议 (广域)</text>
</g>
<!-- NODE 3: Cloud SCADA (Top Right) -->
<g transform="translate(1350, 300)">
<!-- Server rack isometric abstraction -->
<g stroke="var(--neon-cyan-dim)" stroke-width="1.5" fill="#0f172a">
<path d="M -60 20 L 0 40 L 60 20 L 0 0 Z" />
<path d="M -60 0 L 0 20 L 60 0 L 0 -20 Z" />
<path d="M -60 -20 L 0 0 L 60 -20 L 0 -40 Z" />
<path d="M -60 -40 L 0 -20 L 60 -40 L 0 -60 Z" />
</g>
<!-- Blinking server lights -->
<circle cx="0" cy="15" r="2" fill="var(--neon-cyan)" filter="url(#glow)">
<animate attributeName="opacity" values="1;0;1" dur="1s" repeatCount="indefinite" />
</circle>
<circle cx="0" cy="-5" r="2" fill="var(--neon-cyan)" filter="url(#glow)">
<animate attributeName="opacity" values="0;1;0" dur="1.2s" repeatCount="indefinite" />
</circle>
<text x="0" y="70" class="text-svg-title">云端指挥中心</text>
<text x="0" y="90" class="text-svg">SCADA / 远程诊断</text>
</g>
<!-- NODE 4: Mobile APP (Bottom Right) -->
<g transform="translate(1350, 600)">
<!-- Phone outline -->
<rect x="-30" y="-55" width="60" height="110" rx="8" class="node-base" />
<rect x="-25" y="-45" width="50" height="80" rx="4" fill="#1e293b" />
<line x1="-10" y1="-50" x2="10" y2="-50" stroke="#334155" stroke-width="2" stroke-linecap="round" />
<!-- App UI mock -->
<circle cx="-10" cy="-30" r="5" fill="var(--neon-cyan)" opacity="0.8" />
<rect x="0" y="-33" width="20" height="4" fill="#475569" />
<circle cx="-10" cy="-15" r="5" fill="var(--neon-cyan)" opacity="0.8" />
<rect x="0" y="-18" width="15" height="4" fill="#475569" />
<text x="0" y="85" class="text-svg-title">移动端 APP</text>
<text x="0" y="105" class="text-svg">实时监控与报警推送</text>
</g>
<!-- ============================== ANIMATED DATA FLOWS ============================== -->
<!-- 2秒/次 continuous upload flow (PLC -> GW -> Cloud/APP) -->
<g id="normal-data-flow">
<!-- To Gateway -->
<use href="#packet-up">
<animateMotion dur="1s" repeatCount="indefinite">
<mpath href="#path-plc-gw" />
</animateMotion>
</use>
<use href="#packet-up">
<animateMotion dur="1s" begin="0.5s" repeatCount="indefinite">
<mpath href="#path-plc-gw" />
</animateMotion>
</use>
<!-- Gateway to Cloud -->
<use href="#packet-up">
<animateMotion dur="1s" repeatCount="indefinite">
<mpath href="#path-gw-cloud" />
</animateMotion>
</use>
<use href="#packet-up">
<animateMotion dur="1s" begin="0.5s" repeatCount="indefinite">
<mpath href="#path-gw-cloud" />
</animateMotion>
</use>
<!-- Gateway to APP -->
<use href="#packet-up">
<animateMotion dur="1.2s" repeatCount="indefinite">
<mpath href="#path-gw-app" />
</animateMotion>
</use>
</g>
<!-- Alarm Data Flow (Initially Hidden) -->
<g id="alarm-data-flow" style="display: none;">
<use href="#packet-alarm">
<animateMotion dur="0.8s" repeatCount="indefinite">
<mpath href="#path-plc-gw" />
</animateMotion>
</use>
<use href="#packet-alarm">
<animateMotion dur="0.8s" repeatCount="indefinite">
<mpath href="#path-gw-cloud" />
</animateMotion>
</use>
<use href="#packet-alarm">
<animateMotion dur="0.8s" repeatCount="indefinite">
<mpath href="#path-gw-app" />
</animateMotion>
</use>
</g>
<!-- Fast Control Instruction (Triggered via JS) -->
<use href="#packet-down" id="control-packet" style="display: none;">
<!-- Animation defined in JS to allow re-triggering -->
</use>
</svg>
</div>
<script>
// =========================================
// INTERACTIVITY & LOGIC
// =========================================
document.addEventListener('DOMContentLoaded', () => {
const btnAlarm = document.getElementById('btn-alarm');
const btnControl = document.getElementById('btn-control');
const normalFlow = document.getElementById('normal-data-flow');
const alarmFlow = document.getElementById('alarm-data-flow');
const container = document.getElementById('animation-container');
const plcAlarmLight = document.getElementById('plc-alarm-light');
const controlPacket = document.getElementById('control-packet');
const latencyVal = document.getElementById('latency-val');
let isAlarmActive = false;
// Update latency slightly to simulate live dashboard
setInterval(() => {
const base = isAlarmActive ? 80 : 35;
const jitter = Math.floor(Math.random() * 15);
latencyVal.innerText = `${base + jitter} ms`;
}, 2000);
// Toggle Alarm Simulation
btnAlarm.addEventListener('click', () => {
isAlarmActive = !isAlarmActive;
if (isAlarmActive) {
btnAlarm.classList.add('active');
btnAlarm.innerText = '取消井场异常报警 (⬆)';
container.classList.add('state-alert');
normalFlow.style.display = 'none';
alarmFlow.style.display = 'block';
plcAlarmLight.setAttribute('fill', '#ff2a6d');
plcAlarmLight.setAttribute('filter', 'url(#glow-strong)');
} else {
btnAlarm.classList.remove('active');
btnAlarm.innerText = '触发井场异常报警 (⬆)';
container.classList.remove('state-alert');
normalFlow.style.display = 'block';
alarmFlow.style.display = 'none';
plcAlarmLight.setAttribute('fill', '#334155');
plcAlarmLight.removeAttribute('filter');
}
});
// Trigger Remote Control Instruction (< 1s Latency Demo)
let controlTimeout;
btnControl.addEventListener('click', () => {
// Prevent spamming
if (controlPacket.style.display === 'block') return;
btnControl.innerText = '指令下发中...';
btnControl.style.borderColor = '#ffffff';
btnControl.style.color = '#ffffff';
// Show packet
controlPacket.style.display = 'block';
// Create and append animateMotion dynamically to trigger it immediately
const animateMotion = document.createElementNS('http://www.w3.org/2000/svg', 'animateMotion');
animateMotion.setAttribute('dur', '0.6s'); // Represents < 1s latency
animateMotion.setAttribute('fill', 'freeze');
const mpath = document.createElementNS('http://www.w3.org/2000/svg', 'mpath');
mpath.setAttribute('href', '#path-return');
animateMotion.appendChild(mpath);
controlPacket.appendChild(animateMotion);
// Trigger animation (SMIL beginElement if supported, or rely on insert)
try { animateMotion.beginElement(); } catch(e) {}
// Reset after animation duration
clearTimeout(controlTimeout);
controlTimeout = setTimeout(() => {
controlPacket.style.display = 'none';
controlPacket.innerHTML = ''; // Clean up
btnControl.innerText = '模拟远程下发指令 (⬇)';
btnControl.style.borderColor = '';
btnControl.style.color = '';
// Visual feedback on PLC
const ogColor = plcAlarmLight.getAttribute('fill');
plcAlarmLight.setAttribute('fill', '#ffffff');
setTimeout(() => plcAlarmLight.setAttribute('fill', ogColor), 300);
}, 650); // Slightly longer than dur
});
});
</script>
</body>
</html>
积分规则:每轮对话扣10分
等待动画代码生成...
