1173 lines
48 KiB
HTML
1173 lines
48 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>赛博朋克 2078 - 神经网络城市可视化平台</title>
|
||
|
||
<!-- 引入外部字体 -->
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@300;500;700&display=swap" rel="stylesheet">
|
||
|
||
<!-- 引入 Font Awesome -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
|
||
<!-- 引入样式重置与基础样式 -->
|
||
<style>
|
||
:root {
|
||
--neon-pink: #ff00ff;
|
||
--neon-blue: #00ffff;
|
||
--neon-purple: #8800ff;
|
||
--bg-dark: #050505;
|
||
--bg-panel: rgba(10, 10, 16, 0.85);
|
||
--text-main: #e0e0e0;
|
||
--font-display: 'Orbitron', sans-serif;
|
||
--font-body: 'Rajdhani', sans-serif;
|
||
--border-glow: 0 0 10px rgba(0, 255, 255, 0.5);
|
||
}
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
scrollbar-width: thin;
|
||
scrollbar-color: var(--neon-blue) var(--bg-dark);
|
||
}
|
||
|
||
body {
|
||
background-color: var(--bg-dark);
|
||
color: var(--text-main);
|
||
font-family: var(--font-body);
|
||
overflow-x: hidden;
|
||
background-image:
|
||
radial-gradient(circle at 50% 50%, rgba(0, 255, 255, 0.05) 0%, transparent 50%),
|
||
linear-gradient(rgba(0, 0, 0, 0.8) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(0, 0, 0, 0.8) 1px, transparent 1px);
|
||
background-size: 100% 100%, 40px 40px, 40px 40px;
|
||
}
|
||
|
||
/* 滚动条样式 */
|
||
::-webkit-scrollbar {
|
||
width: 8px;
|
||
}
|
||
::-webkit-scrollbar-track {
|
||
background: #0a0a0a;
|
||
}
|
||
::-webkit-scrollbar-thumb {
|
||
background: var(--neon-blue);
|
||
border-radius: 4px;
|
||
}
|
||
|
||
/* 工具类 */
|
||
.neon-text-blue {
|
||
text-shadow: 0 0 5px var(--neon-blue), 0 0 10px var(--neon-blue);
|
||
color: var(--neon-blue);
|
||
}
|
||
.neon-text-pink {
|
||
text-shadow: 0 0 5px var(--neon-pink), 0 0 10px var(--neon-pink);
|
||
color: var(--neon-pink);
|
||
}
|
||
.glass-panel {
|
||
background: var(--bg-panel);
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid rgba(0, 255, 255, 0.2);
|
||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.glass-panel::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0; left: 0; right: 0; height: 1px;
|
||
background: linear-gradient(90deg, transparent, var(--neon-blue), transparent);
|
||
opacity: 0.5;
|
||
}
|
||
.corner-deco {
|
||
position: absolute;
|
||
width: 10px;
|
||
height: 10px;
|
||
border: 2px solid var(--neon-blue);
|
||
transition: all 0.3s ease;
|
||
}
|
||
.tl { top: -1px; left: -1px; border-right: none; border-bottom: none; }
|
||
.tr { top: -1px; right: -1px; border-left: none; border-bottom: none; }
|
||
.bl { bottom: -1px; left: -1px; border-right: none; border-top: none; }
|
||
.br { bottom: -1px; right: -1px; border-left: none; border-top: none; }
|
||
|
||
/* Glitch 效果 */
|
||
.glitch-wrapper {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
.glitch {
|
||
position: relative;
|
||
color: white;
|
||
font-weight: bold;
|
||
}
|
||
.glitch::before, .glitch::after {
|
||
content: attr(data-text);
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: var(--bg-dark);
|
||
}
|
||
.glitch::before {
|
||
left: 2px;
|
||
text-shadow: -1px 0 var(--neon-pink);
|
||
clip: rect(24px, 550px, 90px, 0);
|
||
animation: glitch-anim-2 3s infinite linear alternate-reverse;
|
||
}
|
||
.glitch::after {
|
||
left: -2px;
|
||
text-shadow: -1px 0 var(--neon-blue);
|
||
clip: rect(85px, 550px, 140px, 0);
|
||
animation: glitch-anim 2.5s infinite linear alternate-reverse;
|
||
}
|
||
@keyframes glitch-anim {
|
||
0% { clip: rect(11px, 9999px, 34px, 0); }
|
||
100% { clip: rect(66px, 9999px, 81px, 0); }
|
||
}
|
||
@keyframes glitch-anim-2 {
|
||
0% { clip: rect(89px, 9999px, 96px, 0); }
|
||
100% { clip: rect(12px, 9999px, 58px, 0); }
|
||
}
|
||
|
||
/* 模块一:开场动画 */
|
||
#intro-overlay {
|
||
position: fixed;
|
||
top: 0; left: 0; width: 100%; height: 100%;
|
||
background: #000;
|
||
z-index: 9999;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
}
|
||
#intro-canvas {
|
||
position: absolute;
|
||
top: 0; left: 0;
|
||
}
|
||
.intro-text {
|
||
font-family: var(--font-display);
|
||
font-size: 3rem;
|
||
color: var(--neon-blue);
|
||
opacity: 0;
|
||
z-index: 10;
|
||
letter-spacing: 5px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
/* 模块二:3D城市概览 */
|
||
#city-view-section {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
}
|
||
#three-canvas {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: block;
|
||
}
|
||
.hud-overlay {
|
||
position: absolute;
|
||
top: 20px;
|
||
right: 20px;
|
||
width: 300px;
|
||
padding: 15px;
|
||
z-index: 10;
|
||
pointer-events: none; /* 让鼠标事件穿透到3D场景 */
|
||
}
|
||
.time-display {
|
||
font-family: var(--font-display);
|
||
font-size: 1.5rem;
|
||
border-bottom: 1px solid var(--neon-pink);
|
||
padding-bottom: 5px;
|
||
margin-bottom: 10px;
|
||
}
|
||
.city-metrics div {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 5px;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
/* 模块三:神经网络可视化 */
|
||
#neural-network-section {
|
||
padding: 50px 20px;
|
||
min-height: 80vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
position: relative;
|
||
}
|
||
#neural-container {
|
||
width: 100%;
|
||
max-width: 1200px;
|
||
height: 500px;
|
||
margin-top: 30px;
|
||
border: 1px solid var(--neon-purple);
|
||
box-shadow: 0 0 20px rgba(136, 0, 255, 0.2);
|
||
background: rgba(0, 0, 0, 0.6);
|
||
}
|
||
.neural-stats {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin-bottom: 20px;
|
||
}
|
||
.stat-box {
|
||
padding: 10px 20px;
|
||
border: 1px solid var(--neon-blue);
|
||
background: rgba(0, 255, 255, 0.05);
|
||
font-family: var(--font-display);
|
||
font-size: 1.2rem;
|
||
}
|
||
|
||
/* 模块四:智能系统监控 */
|
||
#dashboard-section {
|
||
padding: 50px 5%;
|
||
background: linear-gradient(180deg, transparent, rgba(0,0,0,0.8));
|
||
}
|
||
.dashboard-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||
gap: 20px;
|
||
}
|
||
.monitor-card {
|
||
height: 250px;
|
||
padding: 20px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.card-header {
|
||
font-family: var(--font-display);
|
||
color: var(--neon-blue);
|
||
margin-bottom: 15px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
/* 仪表盘 */
|
||
#gauge-container {
|
||
flex: 1;
|
||
position: relative;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
/* 示波器 */
|
||
#oscilloscope-canvas {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: #000;
|
||
}
|
||
/* 服务器网格 */
|
||
.server-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(10, 1fr);
|
||
gap: 5px;
|
||
margin-top: 10px;
|
||
flex: 1;
|
||
}
|
||
.server-node {
|
||
background: #222;
|
||
height: 20px;
|
||
transition: background 0.3s;
|
||
}
|
||
.server-node.active { background: #0f0; box-shadow: 0 0 5px #0f0; }
|
||
.server-node.error { background: #f00; box-shadow: 0 0 5px #f00; }
|
||
/* 日志窗口 */
|
||
.log-window {
|
||
background: #000;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.8rem;
|
||
color: #0f0;
|
||
padding: 10px;
|
||
overflow-y: auto;
|
||
flex: 1;
|
||
border: 1px solid #333;
|
||
height: 150px;
|
||
position: relative;
|
||
}
|
||
.log-window::after {
|
||
content: " ";
|
||
display: block;
|
||
position: absolute;
|
||
top: 0; left: 0; bottom: 0; right: 0;
|
||
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
|
||
background-size: 100% 2px, 3px 100%;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 模块五:时间线导航 */
|
||
#timeline-section {
|
||
padding: 50px 0;
|
||
overflow: hidden;
|
||
}
|
||
.timeline-container {
|
||
display: flex;
|
||
gap: 30px;
|
||
padding: 20px 5%;
|
||
overflow-x: auto;
|
||
padding-bottom: 40px; /* 阴影空间 */
|
||
cursor: grab;
|
||
}
|
||
.timeline-container:active {
|
||
cursor: grabbing;
|
||
}
|
||
.time-node {
|
||
flex: 0 0 auto;
|
||
width: 200px;
|
||
height: 80px;
|
||
border: 1px solid var(--text-main);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
clip-path: polygon(10% 0, 100% 0, 100% 70%, 90% 100%, 0 100%, 0 30%);
|
||
background: rgba(255, 255, 255, 0.05);
|
||
transition: all 0.3s;
|
||
cursor: pointer;
|
||
position: relative;
|
||
}
|
||
.time-node:hover {
|
||
background: rgba(0, 255, 255, 0.2);
|
||
border-color: var(--neon-blue);
|
||
transform: translateY(-5px);
|
||
}
|
||
.time-node.active {
|
||
border-color: var(--neon-pink);
|
||
box-shadow: 0 0 15px var(--neon-pink);
|
||
background: rgba(255, 0, 255, 0.1);
|
||
}
|
||
.node-detail {
|
||
position: absolute;
|
||
bottom: -40px;
|
||
left: 0;
|
||
width: 100%;
|
||
text-align: center;
|
||
font-size: 0.8rem;
|
||
color: var(--neon-blue);
|
||
opacity: 0;
|
||
transition: opacity 0.3s;
|
||
}
|
||
.time-node:hover .node-detail {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* 模块六:全息数据卡片 */
|
||
#hologram-section {
|
||
padding: 100px 5%;
|
||
perspective: 1000px;
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 50px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.holo-card {
|
||
width: 280px;
|
||
height: 380px;
|
||
background: rgba(0, 20, 40, 0.6);
|
||
border: 1px solid rgba(0, 255, 255, 0.3);
|
||
border-radius: 10px;
|
||
transform-style: preserve-3d;
|
||
transform: rotateX(10deg) rotateY(0deg);
|
||
transition: transform 0.1s ease-out, box-shadow 0.3s;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.holo-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: -50%; left: -50%;
|
||
width: 200%; height: 200%;
|
||
background: linear-gradient(45deg, transparent 45%, rgba(0, 255, 255, 0.1) 50%, transparent 55%);
|
||
transform: rotate(45deg);
|
||
animation: shine 3s infinite;
|
||
pointer-events: none;
|
||
}
|
||
@keyframes shine {
|
||
0% { transform: translateX(-100%) rotate(45deg); }
|
||
100% { transform: translateX(100%) rotate(45deg); }
|
||
}
|
||
.holo-card:hover {
|
||
transform: rotateX(0deg) translateY(-20px);
|
||
box-shadow: 0 20px 50px rgba(0, 255, 255, 0.2);
|
||
z-index: 10;
|
||
}
|
||
.holo-content {
|
||
padding: 20px;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
.holo-icon {
|
||
font-size: 3rem;
|
||
color: var(--neon-blue);
|
||
margin-bottom: 20px;
|
||
}
|
||
.holo-data {
|
||
font-size: 2.5rem;
|
||
font-weight: bold;
|
||
font-family: var(--font-display);
|
||
text-align: right;
|
||
}
|
||
.holo-desc {
|
||
font-size: 0.9rem;
|
||
color: #aaa;
|
||
opacity: 0.8;
|
||
}
|
||
.holo-hidden-info {
|
||
height: 0;
|
||
overflow: hidden;
|
||
transition: height 0.3s;
|
||
color: var(--neon-pink);
|
||
}
|
||
.holo-card:hover .holo-hidden-info {
|
||
height: 60px;
|
||
}
|
||
|
||
/* 模块七:命令控制台 */
|
||
#console-section {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
background: rgba(0, 0, 0, 0.9);
|
||
border-top: 1px solid var(--neon-blue);
|
||
padding: 15px;
|
||
display: flex;
|
||
justify-content: center;
|
||
z-index: 1000;
|
||
}
|
||
.console-wrapper {
|
||
width: 100%;
|
||
max-width: 800px;
|
||
position: relative;
|
||
}
|
||
.console-input {
|
||
width: 100%;
|
||
background: transparent;
|
||
border: none;
|
||
border-bottom: 2px solid var(--neon-blue);
|
||
color: var(--neon-blue);
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 1.2rem;
|
||
padding: 5px;
|
||
outline: none;
|
||
}
|
||
.console-input::placeholder {
|
||
color: rgba(0, 255, 255, 0.3);
|
||
}
|
||
.scan-line {
|
||
position: fixed;
|
||
top: 0; left: 0; width: 100%; height: 5px;
|
||
background: var(--neon-blue);
|
||
box-shadow: 0 0 20px var(--neon-blue);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
z-index: 9998;
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 768px) {
|
||
.intro-text { font-size: 2rem; }
|
||
#neural-container { height: 300px; }
|
||
.dashboard-grid { grid-template-columns: 1fr; }
|
||
.holo-card { width: 100%; max-width: 300px; margin: 10px; }
|
||
#hologram-section { flex-direction: column; align-items: center; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- 模块一:沉浸式开场 -->
|
||
<div id="intro-overlay">
|
||
<canvas id="intro-canvas"></canvas>
|
||
<div class="intro-text">NEURAL NETWORK LINKED</div>
|
||
</div>
|
||
|
||
<!-- 扫描线反馈 -->
|
||
<div class="scan-line" id="scan-line"></div>
|
||
|
||
<!-- 主内容区 -->
|
||
<main id="main-content" style="display: none; opacity: 0;">
|
||
|
||
<!-- 模块二:3D城市 -->
|
||
<section id="city-view-section">
|
||
<canvas id="three-canvas"></canvas>
|
||
<div class="glass-panel hud-overlay">
|
||
<div class="corner-deco tl"></div><div class="corner-deco tr"></div>
|
||
<div class="corner-deco bl"></div><div class="corner-deco br"></div>
|
||
<div class="time-display" id="clock">2078.01.01 00:00:00</div>
|
||
<div class="city-metrics">
|
||
<div><span>电网负载</span> <span class="neon-text-blue">87%</span></div>
|
||
<div><span>网络延迟</span> <span class="neon-text-pink">12ms</span></div>
|
||
<div><span>安全等级</span> <span style="color:#0f0">稳定</span></div>
|
||
<div><span>活跃节点</span> <span>4,096</span></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 模块三:神经网络 -->
|
||
<section id="neural-network-section">
|
||
<h2 class="neon-text-blue glitch-wrapper"><span class="glitch" data-text="NEURAL DATA STREAM">NEURAL DATA STREAM</span></h2>
|
||
<div class="neural-stats">
|
||
<div class="stat-box">神经元活跃度: <span id="neuron-activity">98.2%</span></div>
|
||
<div class="stat-box">数据吞吐: <span id="throughput">402 TB/s</span></div>
|
||
</div>
|
||
<div id="neural-container"></div>
|
||
</section>
|
||
|
||
<!-- 模块四:系统监控 -->
|
||
<section id="dashboard-section">
|
||
<h2 class="neon-text-pink" style="margin-bottom: 30px;">SYSTEM MONITOR</h2>
|
||
<div class="dashboard-grid">
|
||
<!-- CPU 仪表 -->
|
||
<div class="glass-panel monitor-card">
|
||
<div class="card-header"><span><i class="fas fa-microchip"></i> CPU LOAD</span> <span id="cpu-val">45%</span></div>
|
||
<div id="gauge-container">
|
||
<svg width="150" height="80" viewBox="0 0 150 80">
|
||
<path d="M10,70 A65,65 0 0,1 140,70" fill="none" stroke="#333" stroke-width="10" stroke-linecap="round"/>
|
||
<path id="gauge-path" d="M10,70 A65,65 0 0,1 140,70" fill="none" stroke="var(--neon-blue)" stroke-width="10" stroke-linecap="round" stroke-dasharray="200" stroke-dashoffset="100"/>
|
||
<text x="75" y="50" text-anchor="middle" fill="#fff" font-family="Orbitron" font-size="20" id="gauge-text">45%</text>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 网络流量 -->
|
||
<div class="glass-panel monitor-card">
|
||
<div class="card-header"><span><i class="fas fa-wifi"></i> NET TRAFFIC</span> <span>Live</span></div>
|
||
<canvas id="oscilloscope-canvas"></canvas>
|
||
</div>
|
||
|
||
<!-- 服务器状态 -->
|
||
<div class="glass-panel monitor-card">
|
||
<div class="card-header"><span><i class="fas fa-server"></i> CLUSTER STATUS</span> <span>Online</span></div>
|
||
<div class="server-grid" id="server-grid">
|
||
<!-- JS 生成节点 -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 系统日志 -->
|
||
<div class="glass-panel monitor-card">
|
||
<div class="card-header"><span><i class="fas fa-terminal"></i> SYSTEM LOGS</span></div>
|
||
<div class="log-window" id="system-log">
|
||
<div>[SYSTEM] Boot sequence initialized...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 模块五:时间线 -->
|
||
<section id="timeline-section">
|
||
<h2 class="neon-text-blue" style="text-align: center; margin-bottom: 20px;">HISTORICAL ARCHIVES</h2>
|
||
<div class="timeline-container" id="timeline">
|
||
<!-- JS 生成时间节点 -->
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 模块六:全息卡片 -->
|
||
<section id="hologram-section">
|
||
<div class="holo-card">
|
||
<div class="holo-content">
|
||
<div>
|
||
<i class="fas fa-users holo-icon"></i>
|
||
<div class="holo-data">14.2M</div>
|
||
<div class="holo-desc">CITY POPULATION</div>
|
||
</div>
|
||
<div class="holo-hidden-info">
|
||
<p>自然增长: 0.5%</p>
|
||
<p>移民流入: 120k/yr</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="holo-card">
|
||
<div class="holo-content">
|
||
<div>
|
||
<i class="fas fa-bolt holo-icon" style="color: var(--neon-pink)"></i>
|
||
<div class="holo-data">850 GW</div>
|
||
<div class="holo-desc">ENERGY CONSUMPTION</div>
|
||
</div>
|
||
<div class="holo-hidden-info">
|
||
<p>聚变贡献: 80%</p>
|
||
<p>太阳能: 15%</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="holo-card">
|
||
<div class="holo-content">
|
||
<div>
|
||
<i class="fas fa-brain holo-icon" style="color: var(--neon-purple)"></i>
|
||
<div class="holo-data">99.9%</div>
|
||
<div class="holo-desc">AI SYNC RATE</div>
|
||
</div>
|
||
<div class="holo-hidden-info">
|
||
<p>核心: 'Central'</p>
|
||
<p>子节点: 504 connected</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 底部占位 -->
|
||
<footer style="height: 100px; display: flex; align-items: center; justify-content: center; color: #555;">
|
||
<p>© 2078 NEURAL NETWORK CITY CORP. ALL RIGHTS RESERVED.</p>
|
||
</footer>
|
||
|
||
</main>
|
||
|
||
<!-- 模块七:控制台 -->
|
||
<div id="console-section">
|
||
<div class="console-wrapper">
|
||
<input type="text" class="console-input" id="command-input" placeholder="ENTER COMMAND (e.g., 'SYSTEM DIAGNOSTIC')..." autocomplete="off">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 引入外部脚本库 -->
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
|
||
<!-- 主逻辑脚本 -->
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
|
||
// ==========================================
|
||
// 模块一:沉浸式开场动画
|
||
// ==========================================
|
||
const introCanvas = document.getElementById('intro-canvas');
|
||
const introCtx = introCanvas.getContext('2d');
|
||
const introOverlay = document.getElementById('intro-overlay');
|
||
const introText = document.querySelector('.intro-text');
|
||
const mainContent = document.getElementById('main-content');
|
||
|
||
let introWidth, introHeight; // 修正:变量重名
|
||
let introFrame = 0;
|
||
const totalIntroFrames = 180; // 约3秒
|
||
|
||
function resizeIntro() {
|
||
introWidth = window.innerWidth;
|
||
introHeight = window.innerHeight;
|
||
introCanvas.width = introWidth;
|
||
introCanvas.height = introHeight;
|
||
}
|
||
window.addEventListener('resize', resizeIntro);
|
||
resizeIntro();
|
||
|
||
const nodes = Array.from({length: 50}, () => ({
|
||
x: Math.random() * introWidth,
|
||
y: Math.random() * introHeight,
|
||
vx: (Math.random() - 0.5) * 2,
|
||
vy: (Math.random() - 0.5) * 2
|
||
}));
|
||
|
||
function playIntro() {
|
||
if (introFrame > totalIntroFrames) {
|
||
// 动画结束,过渡到主界面
|
||
gsap.to(introOverlay, { opacity: 0, duration: 1, onComplete: () => {
|
||
introOverlay.style.display = 'none';
|
||
mainContent.style.display = 'block';
|
||
gsap.to(mainContent, { opacity: 1, duration: 1.5 });
|
||
}});
|
||
return;
|
||
}
|
||
|
||
introCtx.fillStyle = 'rgba(0, 0, 0, 0.1)';
|
||
introCtx.fillRect(0, 0, introWidth, introHeight);
|
||
|
||
const progress = introFrame / totalIntroFrames;
|
||
const centerX = introWidth / 2;
|
||
const centerY = introHeight / 2;
|
||
const maxDist = Math.max(introWidth, introHeight) * 0.8;
|
||
|
||
// 更新节点位置
|
||
introCtx.fillStyle = '#00ffff';
|
||
nodes.forEach(node => {
|
||
node.x += node.vx;
|
||
node.y += node.vy;
|
||
|
||
// 边界反弹
|
||
if(node.x < 0 || node.x > introWidth) node.vx *= -1;
|
||
if(node.y < 0 || node.y > introHeight) node.vy *= -1;
|
||
|
||
// 绘制节点
|
||
const dist = Math.sqrt((node.x - centerX)**2 + (node.y - centerY)**2);
|
||
|
||
// 随着动画进行,限制节点范围向内收缩,然后反向扩散
|
||
// 简化:始终绘制连线,最后文字显现
|
||
introCtx.beginPath();
|
||
introCtx.arc(node.x, node.y, 2, 0, Math.PI * 2);
|
||
introCtx.fill();
|
||
|
||
// 连线
|
||
nodes.forEach(other => {
|
||
const d = Math.sqrt((node.x - other.x)**2 + (node.y - other.y)**2);
|
||
if (d < 150) {
|
||
introCtx.strokeStyle = `rgba(0, 255, 255, ${1 - d/150})`;
|
||
introCtx.beginPath();
|
||
introCtx.moveTo(node.x, node.y);
|
||
introCtx.lineTo(other.x, other.y);
|
||
introCtx.stroke();
|
||
}
|
||
});
|
||
});
|
||
|
||
// 文字渐显
|
||
if (introFrame > 100) {
|
||
introText.style.opacity = (introFrame - 100) / 80;
|
||
}
|
||
|
||
introFrame++;
|
||
requestAnimationFrame(playIntro);
|
||
}
|
||
playIntro();
|
||
|
||
// ==========================================
|
||
// 模块二:Three.js 3D城市 (优化版)
|
||
// ==========================================
|
||
const threeCanvas = document.getElementById('three-canvas');
|
||
const scene = new THREE.Scene();
|
||
scene.fog = new THREE.FogExp2(0x050505, 0.0025);
|
||
|
||
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||
camera.position.set(0, 40, 60);
|
||
camera.lookAt(0, 0, 0);
|
||
|
||
const renderer = new THREE.WebGLRenderer({ canvas: threeCanvas, antialias: true, alpha: true });
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // 性能优化:限制像素比
|
||
|
||
// 城市生成逻辑
|
||
const cityGroup = new THREE.Group();
|
||
scene.add(cityGroup);
|
||
|
||
const buildingGeo = new THREE.BoxGeometry(1, 1, 1);
|
||
buildingGeo.translate(0, 0.5, 0);
|
||
|
||
// 使用Phong材质,但去除过多光照计算
|
||
const buildingMat = new THREE.MeshPhongMaterial({
|
||
color: 0x111111,
|
||
emissive: 0x000510, // 微弱自发光
|
||
specular: 0x111111,
|
||
shininess: 30,
|
||
flatShading: true
|
||
});
|
||
|
||
// 霓虹灯材质 (使用BasicMaterial,不受光照影响,模拟发光效果)
|
||
const neonColors = [0x00ffff, 0xff00ff, 0x8800ff, 0x00ff00];
|
||
const neonGeo = new THREE.BoxGeometry(0.8, 0.2, 0.8);
|
||
neonGeo.translate(0, 0.1, 0);
|
||
|
||
const gridSize = 40;
|
||
const spacing = 1.5;
|
||
|
||
// 存储所有霓虹灯,以便后续交互变色
|
||
const neonLightsMeshes = [];
|
||
|
||
for (let x = -gridSize/2; x < gridSize/2; x++) {
|
||
for (let z = -gridSize/2; z < gridSize/2; z++) {
|
||
const dist = Math.sqrt(x*x + z*z);
|
||
const maxH = Math.max(2, (gridSize/2 - dist) * 2 + Math.random() * 5);
|
||
const height = Math.random() * maxH;
|
||
|
||
if (height < 1) continue;
|
||
|
||
const building = new THREE.Mesh(buildingGeo, buildingMat);
|
||
building.position.set(x * spacing, 0, z * spacing);
|
||
building.scale.set(1, height, 1);
|
||
cityGroup.add(building);
|
||
|
||
// 添加简单的侧面线条作为LED
|
||
const edges = new THREE.EdgesGeometry(buildingGeo);
|
||
const lineMat = new THREE.LineBasicMaterial({ color: 0x001133, transparent: true, opacity: 0.3 });
|
||
const lines = new THREE.LineSegments(edges, lineMat);
|
||
lines.position.copy(building.position);
|
||
lines.scale.copy(building.scale);
|
||
cityGroup.add(lines);
|
||
|
||
// 使用自发光几何体代替 PointLight
|
||
// 30%的建筑物顶部有霓虹灯
|
||
if (Math.random() > 0.7) {
|
||
const color = neonColors[Math.floor(Math.random() * neonColors.length)];
|
||
const neonMat = new THREE.MeshBasicMaterial({ color: color });
|
||
const neonMesh = new THREE.Mesh(neonGeo, neonMat);
|
||
|
||
// 放置在建筑物顶部
|
||
neonMesh.position.set(x * spacing, height, z * spacing);
|
||
|
||
// 随机缩放一点
|
||
const scale = 0.8 + Math.random() * 0.4;
|
||
neonMesh.scale.set(scale, 1, scale);
|
||
|
||
cityGroup.add(neonMesh);
|
||
neonLightsMeshes.push(neonMesh); // 存储以便后续控制
|
||
}
|
||
}
|
||
}
|
||
|
||
// 地面网格
|
||
const gridHelper = new THREE.GridHelper(100, 100, 0xff00ff, 0x111111);
|
||
scene.add(gridHelper);
|
||
|
||
// 优化的光照系统:仅保留少量强光源
|
||
const ambientLight = new THREE.AmbientLight(0x404040, 1.5); // 增强环境光
|
||
scene.add(ambientLight);
|
||
|
||
const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
|
||
dirLight.position.set(50, 100, 50);
|
||
scene.add(dirLight);
|
||
|
||
// 添加几个移动的彩色点光源来模拟巡逻车或无人机,营造动态氛围
|
||
const movingLights = [];
|
||
const lightColors = [0x00ffff, 0xff00ff, 0x00ff00];
|
||
for(let i=0; i<5; i++) {
|
||
const light = new THREE.PointLight(lightColors[i % 3], 2, 40);
|
||
light.position.set((Math.random()-0.5)*60, 20, (Math.random()-0.5)*60);
|
||
scene.add(light);
|
||
movingLights.push({
|
||
light: light,
|
||
speedX: (Math.random() - 0.5) * 0.2,
|
||
speedZ: (Math.random() - 0.5) * 0.2
|
||
});
|
||
}
|
||
|
||
// 粒子流 (模拟飞行载具)
|
||
const particlesGeo = new THREE.BufferGeometry();
|
||
const particleCount = 200;
|
||
const posArray = new Float32Array(particleCount * 3);
|
||
const speedArray = [];
|
||
|
||
for(let i=0; i<particleCount*3; i+=3) {
|
||
posArray[i] = (Math.random() - 0.5) * 80; // x
|
||
posArray[i+1] = Math.random() * 20 + 5; // y
|
||
posArray[i+2] = (Math.random() - 0.5) * 80; // z
|
||
speedArray.push({
|
||
x: (Math.random() - 0.5) * 0.2,
|
||
y: 0,
|
||
z: (Math.random() - 0.5) * 0.2
|
||
});
|
||
}
|
||
particlesGeo.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
|
||
const particlesMat = new THREE.PointsMaterial({
|
||
size: 0.3,
|
||
color: 0xff00ff,
|
||
transparent: true,
|
||
opacity: 0.8
|
||
});
|
||
const particleSystem = new THREE.Points(particlesGeo, particlesMat);
|
||
scene.add(particleSystem);
|
||
|
||
// 交互:鼠标拖拽
|
||
let isDragging = false;
|
||
let previousMousePosition = { x: 0, y: 0 };
|
||
let targetRotationX = 0;
|
||
let targetRotationY = 0;
|
||
|
||
threeCanvas.addEventListener('mousedown', () => isDragging = true);
|
||
document.addEventListener('mouseup', () => isDragging = false);
|
||
document.addEventListener('mousemove', (e) => {
|
||
if (isDragging) {
|
||
const deltaMove = {
|
||
x: e.offsetX - previousMousePosition.x,
|
||
y: e.offsetY - previousMousePosition.y
|
||
};
|
||
targetRotationY += deltaMove.x * 0.005;
|
||
targetRotationX += deltaMove.y * 0.005;
|
||
targetRotationX = Math.max(-Math.PI/4, Math.min(Math.PI/4, targetRotationX));
|
||
}
|
||
previousMousePosition = { x: e.offsetX, y: e.offsetY };
|
||
});
|
||
|
||
threeCanvas.addEventListener('wheel', (e) => {
|
||
e.preventDefault();
|
||
camera.position.z += e.deltaY * 0.05;
|
||
camera.position.z = Math.max(20, Math.min(100, camera.position.z));
|
||
});
|
||
|
||
// 3D动画循环
|
||
function animateThree() {
|
||
requestAnimationFrame(animateThree);
|
||
|
||
// 平滑旋转
|
||
cityGroup.rotation.y += (targetRotationY - cityGroup.rotation.y) * 0.1;
|
||
cityGroup.rotation.x += (targetRotationX - cityGroup.rotation.x) * 0.1;
|
||
|
||
// 粒子运动
|
||
const positions = particleSystem.geometry.attributes.position.array;
|
||
for(let i=0; i<particleCount; i++) {
|
||
positions[i*3] += speedArray[i].x;
|
||
positions[i*3+1] += speedArray[i].y;
|
||
positions[i*3+2] += speedArray[i].z;
|
||
|
||
if(Math.abs(positions[i*3]) > 40) positions[i*3] *= -0.9;
|
||
if(Math.abs(positions[i*3+2]) > 40) positions[i*3+2] *= -0.9;
|
||
}
|
||
particleSystem.geometry.attributes.position.needsUpdate = true;
|
||
|
||
// 移动灯光动画
|
||
movingLights.forEach(obj => {
|
||
obj.light.position.x += obj.speedX;
|
||
obj.light.position.z += obj.speedZ;
|
||
if(Math.abs(obj.light.position.x) > 50) obj.speedX *= -1;
|
||
if(Math.abs(obj.light.position.z) > 50) obj.speedZ *= -1;
|
||
});
|
||
|
||
if(!isDragging) {
|
||
targetRotationY += 0.001;
|
||
}
|
||
|
||
renderer.render(scene, camera);
|
||
}
|
||
animateThree();
|
||
|
||
window.addEventListener('resize', () => {
|
||
camera.aspect = window.innerWidth / window.innerHeight;
|
||
camera.updateProjectionMatrix();
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
});
|
||
|
||
|
||
// ==========================================
|
||
// 模块三:D3.js 神经网络 (修正变量重名)
|
||
// ==========================================
|
||
const neuralContainer = document.getElementById('neural-container');
|
||
const neuralWidth = neuralContainer.clientWidth;
|
||
const neuralHeight = neuralContainer.clientHeight;
|
||
|
||
const svg = d3.select("#neural-container").append("svg")
|
||
.attr("width", "100%")
|
||
.attr("height", "100%");
|
||
|
||
const defs = svg.append("defs");
|
||
const gradient = defs.append("linearGradient")
|
||
.attr("id", "pulse-gradient")
|
||
.attr("x1", "0%").attr("y1", "0%")
|
||
.attr("x2", "100%").attr("y2", "0%");
|
||
gradient.append("stop").attr("offset", "0%").attr("stop-color", "rgba(0,255,255,0)");
|
||
gradient.append("stop").attr("offset", "50%").attr("stop-color", "rgba(0,255,255,1)");
|
||
gradient.append("stop").attr("offset", "100%").attr("stop-color", "rgba(0,255,255,0)");
|
||
|
||
const nodesData = Array.from({length: 30}, (_, i) => ({ id: i }));
|
||
const linksData = [];
|
||
for(let i=0; i<30; i++) {
|
||
const target = Math.floor(Math.random() * 30);
|
||
if(i !== target) linksData.push({ source: i, target: target });
|
||
}
|
||
|
||
const simulation = d3.forceSimulation(nodesData)
|
||
.force("link", d3.forceLink(linksData).id(d => d.id).distance(100))
|
||
.force("charge", d3.forceManyBody().strength(-200))
|
||
.force("center", d3.forceCenter(neuralWidth / 2, neuralHeight / 2));
|
||
|
||
const link = svg.append("g").selectAll("line").data(linksData).join("line")
|
||
.attr("stroke", "#333").attr("stroke-width", 1);
|
||
|
||
const pulses = svg.append("g").selectAll("circle").data(linksData).join("circle")
|
||
.attr("r", 2).attr("fill", "var(--neon-blue)")
|
||
.style("filter", "drop-shadow(0 0 2px var(--neon-blue))");
|
||
|
||
const node = svg.append("g").selectAll("circle").data(nodesData).join("circle")
|
||
.attr("r", 5).attr("fill", "#000").attr("stroke", "var(--neon-pink)").attr("stroke-width", 2)
|
||
.call(d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended));
|
||
|
||
simulation.on("tick", () => {
|
||
link.attr("x1", d => d.source.x).attr("y1", d => d.source.y)
|
||
.attr("x2", d => d.target.x).attr("y2", d => d.target.y);
|
||
node.attr("cx", d => d.x).attr("cy", d => d.y);
|
||
const time = Date.now() * 0.001;
|
||
pulses.attr("cx", d => d.source.x + (d.target.x - d.source.x) * ((time + d.index) % 1))
|
||
.attr("cy", d => d.source.y + (d.target.y - d.source.y) * ((time + d.index) % 1));
|
||
});
|
||
|
||
function dragstarted(event, d) { if (!event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; }
|
||
function dragged(event, d) { d.fx = event.x; d.fy = event.y; }
|
||
function dragended(event, d) { if (!event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; }
|
||
|
||
window.addEventListener('resize', () => {
|
||
const w = neuralContainer.clientWidth;
|
||
const h = neuralContainer.clientHeight;
|
||
simulation.force("center", d3.forceCenter(w / 2, h / 2));
|
||
simulation.alpha(0.3).restart();
|
||
});
|
||
|
||
|
||
// ==========================================
|
||
// 模块四:仪表盘逻辑
|
||
// ==========================================
|
||
const gaugePath = document.getElementById('gauge-path');
|
||
const gaugeText = document.getElementById('gauge-text');
|
||
const cpuVal = document.getElementById('cpu-val');
|
||
|
||
function updateGauge() {
|
||
const val = Math.floor(30 + Math.random() * 50);
|
||
const offset = 200 - (val / 100) * 200;
|
||
gaugePath.style.strokeDashoffset = offset;
|
||
gaugeText.textContent = val + '%';
|
||
cpuVal.textContent = val + '%';
|
||
if(val > 80) gaugePath.style.stroke = 'var(--neon-pink)';
|
||
else gaugePath.style.stroke = 'var(--neon-blue)';
|
||
}
|
||
setInterval(updateGauge, 2000);
|
||
|
||
const oscCanvas = document.getElementById('oscilloscope-canvas');
|
||
const oscCtx = oscCanvas.getContext('2d');
|
||
let oscOffset = 0;
|
||
function resizeOsc() {
|
||
oscCanvas.width = oscCanvas.parentElement.clientWidth;
|
||
oscCanvas.height = oscCanvas.parentElement.clientHeight - 40;
|
||
}
|
||
window.addEventListener('resize', resizeOsc);
|
||
resizeOsc();
|
||
function drawOscilloscope() {
|
||
requestAnimationFrame(drawOscilloscope);
|
||
const w = oscCanvas.width, h = oscCanvas.height;
|
||
oscCtx.fillStyle = 'rgba(0,0,0,0.1)'; oscCtx.fillRect(0, 0, w, h);
|
||
oscCtx.beginPath(); oscCtx.strokeStyle = '#0f0'; oscCtx.lineWidth = 2;
|
||
for(let x=0; x<w; x++) {
|
||
const y = h/2 + Math.sin((x + oscOffset) * 0.05) * (h/3) + Math.sin((x + oscOffset * 2) * 0.1) * (h/6);
|
||
if(x===0) oscCtx.moveTo(x, y); else oscCtx.lineTo(x, y);
|
||
}
|
||
oscCtx.stroke(); oscOffset += 2;
|
||
}
|
||
drawOscilloscope();
|
||
|
||
const serverGrid = document.getElementById('server-grid');
|
||
for(let i=0; i<40; i++) {
|
||
const div = document.createElement('div'); div.className = 'server-node active'; serverGrid.appendChild(div);
|
||
}
|
||
setInterval(() => {
|
||
const nodes = document.querySelectorAll('.server-node');
|
||
const randIndex = Math.floor(Math.random() * nodes.length);
|
||
nodes[randIndex].className = `server-node ${Math.random() > 0.9 ? 'error' : 'active'}`;
|
||
}, 500);
|
||
|
||
const logWindow = document.getElementById('system-log');
|
||
const logs = ["Data packet received from Node_44", "Encryption key rotation successful", "Connection timeout: Port 8080", "Neural sync rate optimized", "Energy spike detected in Sector 7", "Firewall breach attempt blocked", "Garbage collection started"];
|
||
setInterval(() => {
|
||
const log = document.createElement('div');
|
||
log.textContent = `[${new Date().toLocaleTimeString()}] ${logs[Math.floor(Math.random()*logs.length)]}`;
|
||
logWindow.appendChild(log);
|
||
logWindow.scrollTop = logWindow.scrollHeight;
|
||
if(logWindow.children.length > 20) logWindow.removeChild(logWindow.firstChild);
|
||
}, 1500);
|
||
|
||
|
||
// ==========================================
|
||
// 模块五:交互式时间线
|
||
// ==========================================
|
||
const timelineContainer = document.getElementById('timeline');
|
||
const years = [2024, 2035, 2050, 2065, 2070, 2078];
|
||
|
||
years.forEach((year, index) => {
|
||
const node = document.createElement('div');
|
||
node.className = 'time-node';
|
||
if(index === years.length - 1) node.classList.add('active');
|
||
node.innerHTML = `${year}<div class="node-detail">CLICK TO VIEW ARCHIVE</div>`;
|
||
node.addEventListener('click', () => {
|
||
document.querySelectorAll('.time-node').forEach(n => n.classList.remove('active'));
|
||
node.classList.add('active');
|
||
const ratio = (year - 2024) / (2078 - 2024);
|
||
const r = Math.floor(ratio * 255), g = Math.floor((1-ratio) * 255);
|
||
const color = new THREE.Color(`rgb(${r}, ${g}, 255)`);
|
||
// 修改霓虹灯光颜色
|
||
neonLightsMeshes.forEach(mesh => {
|
||
if (Math.random() > 0.5) mesh.material.color.set(color);
|
||
});
|
||
const log = document.createElement('div');
|
||
log.style.color = "var(--neon-pink)";
|
||
log.textContent = `[USER] Switching view to Year ${year}...`;
|
||
logWindow.appendChild(log);
|
||
logWindow.scrollTop = logWindow.scrollHeight;
|
||
});
|
||
timelineContainer.appendChild(node);
|
||
});
|
||
|
||
let isDown = false, startX, scrollLeft;
|
||
timelineContainer.addEventListener('mousedown', (e) => { isDown = true; startX = e.pageX - timelineContainer.offsetLeft; scrollLeft = timelineContainer.scrollLeft; });
|
||
timelineContainer.addEventListener('mouseleave', () => isDown = false);
|
||
timelineContainer.addEventListener('mouseup', () => isDown = false);
|
||
timelineContainer.addEventListener('mousemove', (e) => {
|
||
if(!isDown) return; e.preventDefault();
|
||
const x = e.pageX - timelineContainer.offsetLeft;
|
||
timelineContainer.scrollLeft = scrollLeft - (x - startX) * 2;
|
||
});
|
||
|
||
|
||
// ==========================================
|
||
// 模块六:全息卡片交互
|
||
// ==========================================
|
||
const cards = document.querySelectorAll('.holo-card');
|
||
cards.forEach(card => {
|
||
card.addEventListener('mousemove', (e) => {
|
||
const rect = card.getBoundingClientRect();
|
||
const x = e.clientX - rect.left, y = e.clientY - rect.top;
|
||
const centerX = rect.width / 2, centerY = rect.height / 2;
|
||
const rotateX = ((y - centerY) / centerY) * -10;
|
||
const rotateY = ((x - centerX) / centerX) * 10;
|
||
card.style.transform = `rotateX(${10 + rotateX}deg) rotateY(${rotateY}deg) translateY(-20px)`;
|
||
});
|
||
card.addEventListener('mouseleave', () => { card.style.transform = `rotateX(10deg) rotateY(0deg)`; });
|
||
});
|
||
|
||
|
||
// ==========================================
|
||
// 模块七:命令控制台
|
||
// ==========================================
|
||
const commandInput = document.getElementById('command-input');
|
||
const scanLine = document.getElementById('scan-line');
|
||
|
||
function triggerScan() {
|
||
const tl = gsap.timeline();
|
||
tl.to(scanLine, { top: "100%", opacity: 1, duration: 1.5, ease: "power2.inOut" })
|
||
.to(scanLine, { opacity: 0, duration: 0.1 });
|
||
}
|
||
|
||
commandInput.addEventListener('keydown', (e) => {
|
||
if (e.key === 'Enter') {
|
||
const cmd = commandInput.value.toUpperCase().trim();
|
||
if (!cmd) return;
|
||
const userLog = document.createElement('div');
|
||
userLog.style.color = "#fff"; userLog.textContent = `> USER: ${cmd}`;
|
||
logWindow.appendChild(userLog); commandInput.value = '';
|
||
triggerScan();
|
||
setTimeout(() => {
|
||
const resLog = document.createElement('div');
|
||
resLog.style.color = "var(--neon-blue)";
|
||
if (cmd.includes('ENERGY')) {
|
||
resLog.textContent = `[SYSTEM] Displaying Energy Grid Map...`;
|
||
neonLightsMeshes.forEach(mesh => mesh.material.color.setHex(0xffff00));
|
||
} else if (cmd.includes('DIAGNOSTIC')) {
|
||
resLog.textContent = `[SYSTEM] Diagnostic Complete: 98% Systems Optimal.`;
|
||
} else if (cmd.includes('RESET')) {
|
||
resLog.textContent = `[SYSTEM] View Reset to Default.`;
|
||
neonLightsMeshes.forEach(mesh => mesh.material.color.setHex(neonColors[Math.floor(Math.random()*neonColors.length)]));
|
||
} else {
|
||
resLog.textContent = `[SYSTEM] Command "${cmd}" recognized. Executing...`;
|
||
}
|
||
logWindow.appendChild(resLog); logWindow.scrollTop = logWindow.scrollHeight;
|
||
}, 800);
|
||
}
|
||
});
|
||
|
||
function updateClock() {
|
||
const now = new Date();
|
||
const year = 2078;
|
||
const timeStr = `${year}.${String(now.getMonth()+1).padStart(2,'0')}.${String(now.getDate()).padStart(2,'0')} ${String(now.getHours()).padStart(2,'0')}:${String(now.getMinutes()).padStart(2,'0')}:${String(now.getSeconds()).padStart(2,'0')}`;
|
||
document.getElementById('clock').textContent = timeStr;
|
||
}
|
||
setInterval(updateClock, 1000); updateClock();
|
||
|
||
setInterval(() => {
|
||
const activity = (95 + Math.random() * 5).toFixed(1);
|
||
const throughput = Math.floor(400 + Math.random() * 50);
|
||
document.getElementById('neuron-activity').textContent = activity + '%';
|
||
document.getElementById('throughput').textContent = throughput + ' TB/s';
|
||
}, 2000);
|
||
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |