feat: 添加赛博朋克风格的单文件HTML网站实现
实现一个完整的赛博朋克2078主题网站,包含3D城市背景、神经网络可视化、全息卡片交互等功能
This commit is contained in:
parent
6a0940081c
commit
4cf9e6d06d
|
|
@ -1,5 +1,5 @@
|
|||
```
|
||||
我需要测试大语言模型的编程能力,请给我一篇prompt,描述生成一套复杂的前端工程,最终展示一个丰富多样,视觉冲击力强的网站。由你定一个内容主题,围绕该主题进行展示
|
||||
我需要测试大语言模型的编程能力,请给我一篇prompt,描述生成一套复杂的前端工程,最终展示一个丰富多样,视觉冲击力强的网站。由你定一个内容主题,围绕该主题进行展示。网站采用单文件 HTML 解决方案(包含 HTML, CSS, JavaScript),并引入 CDN实现复杂效果。注意!我只需要prompt,不要代码实现。
|
||||
```
|
||||
回答 :
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,837 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>CYBERPUNK 2078 | Neural Network City Visualization</title>
|
||||
|
||||
<!-- External Resources -->
|
||||
<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;500;700;900&family=Rajdhani:wght@300;500;700&family=Share+Tech+Mono&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<!-- Libraries -->
|
||||
<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/gsap/3.12.2/ScrollTrigger.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--neon-pink: #ff00ff;
|
||||
--neon-blue: #00ffff;
|
||||
--neon-purple: #8800ff;
|
||||
--neon-green: #00ff41;
|
||||
--dark-bg: #050505;
|
||||
--panel-bg: rgba(10, 10, 16, 0.65);
|
||||
--border-glow: 0 0 10px var(--neon-blue);
|
||||
--text-glow: 0 0 5px currentColor;
|
||||
--font-main: 'Orbitron', sans-serif;
|
||||
--font-body: 'Rajdhani', sans-serif;
|
||||
--font-mono: 'Share Tech Mono', monospace;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--dark-bg);
|
||||
color: #fff;
|
||||
font-family: var(--font-body);
|
||||
overflow-x: hidden;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
/* --- Loading Screen --- */
|
||||
#loader {
|
||||
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;
|
||||
}
|
||||
|
||||
.loader-node {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--neon-blue);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 20px var(--neon-blue);
|
||||
}
|
||||
|
||||
.loader-text {
|
||||
margin-top: 20px;
|
||||
font-family: var(--font-main);
|
||||
color: var(--neon-pink);
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
/* --- 3D Background --- */
|
||||
#canvas-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 0;
|
||||
pointer-events: all; /* Allow 3D interaction */
|
||||
}
|
||||
|
||||
/* --- UI Overlay Layer --- */
|
||||
#ui-layer {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
pointer-events: none; /* Let clicks pass through to 3D where needed */
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Common UI Elements */
|
||||
.hud-panel {
|
||||
background: var(--panel-bg);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(0, 255, 255, 0.2);
|
||||
border-left: 3px solid var(--neon-blue);
|
||||
padding: 15px;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
clip-path: polygon(
|
||||
0 0,
|
||||
100% 0,
|
||||
100% calc(100% - 15px),
|
||||
calc(100% - 15px) 100%,
|
||||
0 100%
|
||||
);
|
||||
}
|
||||
|
||||
.hud-title {
|
||||
font-family: var(--font-main);
|
||||
font-size: 0.9rem;
|
||||
color: var(--neon-blue);
|
||||
text-shadow: var(--text-glow);
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 1px solid rgba(0, 255, 255, 0.3);
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* --- Header / Top Bar --- */
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 30px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: var(--font-main);
|
||||
font-size: 2rem;
|
||||
font-weight: 900;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
text-shadow: 2px 2px 0px var(--neon-pink), -2px -2px 0px var(--neon-blue);
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.sys-status {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
color: var(--neon-green);
|
||||
}
|
||||
|
||||
/* --- Main Content Area --- */
|
||||
main {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr 300px;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
height: calc(100vh - 140px);
|
||||
}
|
||||
|
||||
/* Left Column: Monitoring */
|
||||
.monitor-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
background: rgba(0,0,0,0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.log-window {
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.7rem;
|
||||
color: #aaa;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.log-entry { margin-bottom: 4px; }
|
||||
.log-entry::before { content: '> '; color: var(--neon-pink); }
|
||||
.log-warn { color: #ffff00; }
|
||||
.log-err { color: #ff0000; }
|
||||
|
||||
/* Center Column: Neural Net & Interaction */
|
||||
.center-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#neural-canvas-container {
|
||||
width: 100%;
|
||||
height: 40%;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#neural-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Timeline */
|
||||
.timeline-container {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
background: linear-gradient(90deg, transparent, rgba(0, 255, 255, 0.1), transparent);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow-x: auto;
|
||||
gap: 40px;
|
||||
pointer-events: auto;
|
||||
mask-image: linear-gradient(90deg, transparent, black 20%, black 80%, transparent);
|
||||
}
|
||||
|
||||
.time-node {
|
||||
padding: 5px 15px;
|
||||
border: 1px solid var(--neon-purple);
|
||||
border-radius: 15px;
|
||||
color: var(--neon-purple);
|
||||
cursor: pointer;
|
||||
font-family: var(--font-mono);
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.time-node:hover, .time-node.active {
|
||||
background: var(--neon-purple);
|
||||
color: #fff;
|
||||
box-shadow: 0 0 15px var(--neon-purple);
|
||||
}
|
||||
|
||||
/* Right Column: Holographic Cards */
|
||||
.right-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
perspective: 1000px; /* Essential for 3D tilt */
|
||||
}
|
||||
|
||||
.holo-card {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.01));
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
transform-style: preserve-3d;
|
||||
transition: transform 0.1s ease-out;
|
||||
pointer-events: auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.holo-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%; left: -50%;
|
||||
width: 200%; height: 200%;
|
||||
background: linear-gradient(to bottom right, transparent, rgba(255, 255, 255, 0.1), transparent);
|
||||
transform: rotate(45deg);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.holo-card h3 {
|
||||
font-family: var(--font-main);
|
||||
color: var(--neon-pink);
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.holo-stat {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 5px;
|
||||
font-size: 0.9rem;
|
||||
border-bottom: 1px dashed rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
/* --- Footer / Console --- */
|
||||
footer {
|
||||
padding: 20px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.command-bar {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border: 1px solid var(--neon-blue);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 0 0 20px rgba(0, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.cmd-prompt {
|
||||
color: var(--neon-green);
|
||||
margin-right: 10px;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
#cmd-input {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
text-shadow: 0 0 2px var(--neon-blue);
|
||||
}
|
||||
|
||||
/* --- Glitch Keyframes --- */
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.3; }
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 1024px) {
|
||||
main {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto auto;
|
||||
height: auto;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.center-col { order: -1; height: 400px; }
|
||||
body { overflow-y: auto; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Module 1: Intro Animation -->
|
||||
<div id="loader">
|
||||
<div class="loader-node" id="loader-node"></div>
|
||||
<div class="loader-text">Initializing Neural Uplink...</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 2: Three.js Background -->
|
||||
<div id="canvas-container"></div>
|
||||
|
||||
<!-- Main UI Layer -->
|
||||
<div id="ui-layer">
|
||||
<header>
|
||||
<div class="logo">NightCity<span style="color:var(--neon-blue)">.AI</span></div>
|
||||
<div class="sys-status">
|
||||
<span><i class="fas fa-satellite-dish"></i> CONNECTED</span>
|
||||
<span id="clock">2078.05.12 23:45:01</span>
|
||||
<span style="color:var(--neon-pink)">FPS: <span id="fps-counter">60</span></span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<!-- Module 4: System Monitor -->
|
||||
<aside class="monitor-col">
|
||||
<div class="hud-panel">
|
||||
<div class="hud-title"><span>CPU CORE LOAD</span><span>SYS.01</span></div>
|
||||
<div class="chart-container" id="cpu-chart">
|
||||
<!-- Canvas inserted by JS -->
|
||||
</div>
|
||||
<div style="display:flex; justify-content:space-between; margin-top:5px; font-size:0.8rem;">
|
||||
<span>Core 0: <span style="color:var(--neon-blue)">89%</span></span>
|
||||
<span>Temp: <span style="color:var(--neon-pink)">92°C</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hud-panel">
|
||||
<div class="hud-title"><span>NET TRAFFIC</span><span>TBs/s</span></div>
|
||||
<canvas id="waveform-canvas" height="60" width="260"></canvas>
|
||||
</div>
|
||||
|
||||
<div class="hud-panel">
|
||||
<div class="hud-title"><span>SYSTEM LOGS</span><i class="fas fa-list"></i></div>
|
||||
<div class="log-window" id="log-window">
|
||||
<!-- Logs injected by JS -->
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Module 3 & 5: Center Visuals -->
|
||||
<section class="center-col">
|
||||
<div id="neural-canvas-container">
|
||||
<!-- D3/Canvas Neural Net -->
|
||||
<div style="position:absolute; top:10px; left:10px; font-family:var(--font-mono); font-size:0.7rem; color:rgba(255,255,255,0.5);">
|
||||
NEURAL INTERFACE :: ACTIVE<br>
|
||||
NODES: 4,096<br>
|
||||
SYNAPSE RATE: 99.8%
|
||||
</div>
|
||||
<canvas id="neural-canvas"></canvas>
|
||||
</div>
|
||||
|
||||
<!-- Module 5: Timeline -->
|
||||
<div class="timeline-container">
|
||||
<div class="time-node active" data-year="2078">2078</div>
|
||||
<div class="time-node" data-year="2070">2070</div>
|
||||
<div class="time-node" data-year="2063">2063</div>
|
||||
<div class="time-node" data-year="2055">2055</div>
|
||||
<div class="time-node" data-year="2049">2049</div>
|
||||
<div class="time-node" data-year="2024">2024</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Module 6: Holographic Cards -->
|
||||
<aside class="right-col">
|
||||
<div class="hud-panel holo-card">
|
||||
<h3><i class="fas fa-users"></i> POPULATION</h3>
|
||||
<div class="holo-stat"><span>Citizens</span> <span style="color:var(--neon-blue)">12,405,921</span></div>
|
||||
<div class="holo-stat"><span>Androids</span> <span style="color:var(--neon-purple)">8,200,103</span></div>
|
||||
<div class="holo-stat"><span>Augmented</span> <span style="color:var(--neon-pink)">95.4%</span></div>
|
||||
</div>
|
||||
|
||||
<div class="hud-panel holo-card">
|
||||
<h3><i class="fas fa-bolt"></i> ENERGY GRID</h3>
|
||||
<div class="holo-stat"><span>Fusion Output</span> <span>104%</span></div>
|
||||
<div class="holo-stat"><span>Consumption</span> <span class="blink">CRITICAL</span></div>
|
||||
<div style="width:100%; height:4px; background:#333; margin-top:5px;">
|
||||
<div style="width:85%; height:100%; background:linear-gradient(90deg, var(--neon-blue), var(--neon-pink));"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hud-panel holo-card">
|
||||
<h3><i class="fas fa-network-wired"></i> SECURITY</h3>
|
||||
<div class="holo-stat"><span>Firewall</span> <span style="color:var(--neon-green)">ACTIVE</span></div>
|
||||
<div class="holo-stat"><span>Intrusions</span> <span>0</span></div>
|
||||
<div class="holo-stat"><span>Threat Level</span> <span style="color:var(--neon-blue)">LOW</span></div>
|
||||
</div>
|
||||
</aside>
|
||||
</main>
|
||||
|
||||
<!-- Module 7: Command Console -->
|
||||
<footer>
|
||||
<div class="command-bar">
|
||||
<span class="cmd-prompt">root@nightcity:~#</span>
|
||||
<input type="text" id="cmd-input" placeholder="Enter system command..." autocomplete="off">
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Logic -->
|
||||
<script>
|
||||
// --- Configuration & Global State ---
|
||||
const config = {
|
||||
colors: {
|
||||
pink: 0xff00ff,
|
||||
blue: 0x00ffff,
|
||||
purple: 0x8800ff,
|
||||
black: 0x050505
|
||||
}
|
||||
};
|
||||
|
||||
// --- Module 1: Intro Sequence ---
|
||||
function initIntro() {
|
||||
const tl = gsap.timeline();
|
||||
|
||||
tl.to("#loader-node", {
|
||||
scale: 50,
|
||||
duration: 1.5,
|
||||
ease: "power2.inOut",
|
||||
backgroundColor: "#fff"
|
||||
})
|
||||
.to("#loader", {
|
||||
opacity: 0,
|
||||
duration: 1,
|
||||
pointerEvents: "none",
|
||||
onComplete: () => {
|
||||
initCity3D(); // Start heavy rendering after loader
|
||||
}
|
||||
})
|
||||
.from("header", { y: -50, opacity: 0, duration: 0.5 })
|
||||
.from("main", { opacity: 0, scale: 0.95, duration: 0.8 }, "-=0.3")
|
||||
.from(".command-bar", { y: 50, opacity: 0, duration: 0.5 }, "-=0.5");
|
||||
}
|
||||
|
||||
// --- Module 2: Three.js City ---
|
||||
let scene, camera, renderer, cityGroup;
|
||||
const clock = new THREE.Clock();
|
||||
|
||||
function initCity3D() {
|
||||
const container = document.getElementById('canvas-container');
|
||||
|
||||
// Scene Setup
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(config.colors.black);
|
||||
scene.fog = new THREE.FogExp2(config.colors.black, 0.002);
|
||||
|
||||
// Camera
|
||||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
camera.position.set(0, 40, 80);
|
||||
camera.lookAt(0, 0, 0);
|
||||
|
||||
// Renderer
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
// Lighting
|
||||
const ambientLight = new THREE.AmbientLight(0x404040, 2);
|
||||
scene.add(ambientLight);
|
||||
|
||||
const dirLight = new THREE.DirectionalLight(config.colors.blue, 0.8);
|
||||
dirLight.position.set(100, 100, 50);
|
||||
scene.add(dirLight);
|
||||
|
||||
// City Generation
|
||||
cityGroup = new THREE.Group();
|
||||
const geometry = new THREE.BoxGeometry(1, 1, 1);
|
||||
// Instanced mesh for performance would be better, but simple merging for visual variety here
|
||||
|
||||
const materialCore = new THREE.MeshPhongMaterial({ color: 0x111111, shininess: 100 });
|
||||
const materialGlow = new THREE.LineBasicMaterial({ color: config.colors.blue, transparent: true, opacity: 0.3 });
|
||||
|
||||
for (let i = 0; i < 200; i++) {
|
||||
const h = Math.random() * 20 + 5;
|
||||
const x = (Math.random() - 0.5) * 200;
|
||||
const z = (Math.random() - 0.5) * 200;
|
||||
|
||||
// Building Mesh
|
||||
const building = new THREE.Mesh(geometry, materialCore);
|
||||
building.position.set(x, h/2, z);
|
||||
building.scale.set(Math.random() * 5 + 2, h, Math.random() * 5 + 2);
|
||||
building.castShadow = true;
|
||||
building.receiveShadow = true;
|
||||
|
||||
// Edges (Neon Lines)
|
||||
const edges = new THREE.EdgesGeometry(building.geometry);
|
||||
const line = new THREE.LineSegments(edges, materialGlow);
|
||||
building.add(line);
|
||||
|
||||
cityGroup.add(building);
|
||||
}
|
||||
scene.add(cityGroup);
|
||||
|
||||
// Floor Grid
|
||||
const gridHelper = new THREE.GridHelper(300, 60, config.colors.pink, 0x222222);
|
||||
scene.add(gridHelper);
|
||||
|
||||
// Flying Particles
|
||||
const particlesGeom = new THREE.BufferGeometry();
|
||||
const particleCount = 1000;
|
||||
const posArray = new Float32Array(particleCount * 3);
|
||||
|
||||
for(let i = 0; i < particleCount * 3; i++) {
|
||||
posArray[i] = (Math.random() - 0.5) * 250;
|
||||
}
|
||||
|
||||
particlesGeom.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
|
||||
const particlesMat = new THREE.PointsMaterial({
|
||||
size: 0.5,
|
||||
color: config.colors.pink,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
const particlesMesh = new THREE.Points(particlesGeom, particlesMat);
|
||||
scene.add(particlesMesh);
|
||||
|
||||
// Animation Loop
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
|
||||
const delta = clock.getDelta();
|
||||
const time = clock.getElapsedTime();
|
||||
|
||||
// Rotate City slowly
|
||||
cityGroup.rotation.y = Math.sin(time * 0.05) * 0.1;
|
||||
|
||||
// Move Particles
|
||||
particlesMesh.rotation.y = time * 0.02;
|
||||
particlesMesh.position.y = Math.sin(time * 0.5) * 2 + 10;
|
||||
|
||||
// Camera subtle movement
|
||||
camera.position.x = Math.sin(time * 0.1) * 80;
|
||||
camera.position.z = Math.cos(time * 0.1) * 80;
|
||||
camera.lookAt(0, 10, 0);
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
animate();
|
||||
|
||||
// Resize Handler
|
||||
window.addEventListener('resize', () => {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
});
|
||||
}
|
||||
|
||||
// --- Module 3: Neural Network Canvas ---
|
||||
function initNeuralNet() {
|
||||
const canvas = document.getElementById('neural-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
let nodes = [];
|
||||
let width, height;
|
||||
|
||||
function resize() {
|
||||
const parent = canvas.parentElement;
|
||||
width = parent.clientWidth;
|
||||
height = parent.clientHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
initNodes();
|
||||
}
|
||||
|
||||
function initNodes() {
|
||||
nodes = [];
|
||||
for(let i=0; i<40; i++) {
|
||||
nodes.push({
|
||||
x: Math.random() * width,
|
||||
y: Math.random() * height,
|
||||
vx: (Math.random() - 0.5) * 0.5,
|
||||
vy: (Math.random() - 0.5) * 0.5,
|
||||
pulse: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.fillStyle = '#00ffff';
|
||||
ctx.strokeStyle = 'rgba(0, 255, 255, 0.2)';
|
||||
|
||||
// Draw Connections
|
||||
for(let i=0; i<nodes.length; i++) {
|
||||
let nodeA = nodes[i];
|
||||
|
||||
// Update Position
|
||||
nodeA.x += nodeA.vx;
|
||||
nodeA.y += nodeA.vy;
|
||||
|
||||
// Bounce
|
||||
if(nodeA.x < 0 || nodeA.x > width) nodeA.vx *= -1;
|
||||
if(nodeA.y < 0 || nodeA.y > height) nodeA.vy *= -1;
|
||||
|
||||
// Draw Node
|
||||
ctx.beginPath();
|
||||
ctx.arc(nodeA.x, nodeA.y, 2, 0, Math.PI*2);
|
||||
ctx.fill();
|
||||
|
||||
// Pulse effect
|
||||
if(Math.random() > 0.98) nodeA.pulse = 1;
|
||||
if(nodeA.pulse > 0) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(nodeA.x, nodeA.y, 10 * (1-nodeA.pulse) + 2, 0, Math.PI*2);
|
||||
ctx.strokeStyle = `rgba(255, 0, 255, ${nodeA.pulse})`;
|
||||
ctx.stroke();
|
||||
nodeA.pulse -= 0.05;
|
||||
}
|
||||
|
||||
// Links
|
||||
for(let j=i+1; j<nodes.length; j++) {
|
||||
let nodeB = nodes[j];
|
||||
let dx = nodeA.x - nodeB.x;
|
||||
let dy = nodeA.y - nodeB.y;
|
||||
let dist = Math.sqrt(dx*dx + dy*dy);
|
||||
|
||||
if(dist < 100) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(nodeA.x, nodeA.y);
|
||||
ctx.lineTo(nodeB.x, nodeB.y);
|
||||
ctx.strokeStyle = `rgba(0, 255, 255, ${1 - dist/100})`;
|
||||
ctx.stroke();
|
||||
|
||||
// Data Packet
|
||||
if(Math.random() > 0.99) {
|
||||
ctx.fillStyle = '#fff';
|
||||
let t = (Date.now() % 1000) / 1000;
|
||||
let px = nodeA.x + (nodeB.x - nodeA.x) * t;
|
||||
let py = nodeA.y + (nodeB.y - nodeA.y) * t;
|
||||
ctx.beginPath();
|
||||
ctx.arc(px, py, 1.5, 0, Math.PI*2);
|
||||
ctx.fill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
draw();
|
||||
}
|
||||
|
||||
// --- Module 4: Monitoring Logic ---
|
||||
function initMonitor() {
|
||||
// Clock
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
document.getElementById('clock').innerText = "2078.05.12 " + now.toLocaleTimeString();
|
||||
}, 1000);
|
||||
|
||||
// Log Generator
|
||||
const logs = [
|
||||
"Verifying neural handshake...",
|
||||
"Encryption protocols updated.",
|
||||
"Packet loss detected in Sector 7.",
|
||||
"AI Core temperature stabilizing.",
|
||||
"Warning: Unauthorized scan attempt blocked.",
|
||||
"Syncing timeline database...",
|
||||
"Memory heap optimized."
|
||||
];
|
||||
const logWindow = document.getElementById('log-window');
|
||||
|
||||
setInterval(() => {
|
||||
const p = document.createElement('div');
|
||||
p.className = 'log-entry';
|
||||
const msg = logs[Math.floor(Math.random() * logs.length)];
|
||||
|
||||
// Add color class
|
||||
if(msg.includes("Warning")) p.classList.add('log-warn');
|
||||
|
||||
p.innerText = msg + ` [${Math.floor(Math.random()*999)}]`;
|
||||
logWindow.appendChild(p);
|
||||
logWindow.scrollTop = logWindow.scrollHeight;
|
||||
|
||||
if(logWindow.children.length > 20) logWindow.removeChild(logWindow.firstChild);
|
||||
}, 2000);
|
||||
|
||||
// Waveform (Simple Canvas)
|
||||
const wfCanvas = document.getElementById('waveform-canvas');
|
||||
const wfCtx = wfCanvas.getContext('2d');
|
||||
let offset = 0;
|
||||
|
||||
function drawWave() {
|
||||
wfCtx.fillStyle = 'rgba(0,0,0,0.1)';
|
||||
wfCtx.fillRect(0,0,260,60);
|
||||
wfCtx.lineWidth = 2;
|
||||
wfCtx.strokeStyle = '#00ff41';
|
||||
wfCtx.beginPath();
|
||||
|
||||
for(let x=0; x<260; x+=2) {
|
||||
const y = 30 + Math.sin(x * 0.1 + offset) * 20 * Math.random();
|
||||
if(x===0) wfCtx.moveTo(x,y);
|
||||
else wfCtx.lineTo(x,y);
|
||||
}
|
||||
wfCtx.stroke();
|
||||
offset += 0.2;
|
||||
requestAnimationFrame(drawWave);
|
||||
}
|
||||
drawWave();
|
||||
}
|
||||
|
||||
// --- Module 6: Holo Tilt Effect ---
|
||||
function initHoloCards() {
|
||||
const cards = document.querySelectorAll('.holo-card');
|
||||
|
||||
cards.forEach(card => {
|
||||
card.addEventListener('mousemove', (e) => {
|
||||
const rect = card.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
|
||||
const centerX = rect.width / 2;
|
||||
const centerY = rect.height / 2;
|
||||
|
||||
const rotateX = ((y - centerY) / centerY) * -10; // Max 10deg
|
||||
const rotateY = ((x - centerX) / centerX) * 10;
|
||||
|
||||
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
|
||||
});
|
||||
|
||||
card.addEventListener('mouseleave', () => {
|
||||
card.style.transform = `perspective(1000px) rotateX(0) rotateY(0)`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --- Module 7: Command Console ---
|
||||
function initConsole() {
|
||||
const input = document.getElementById('cmd-input');
|
||||
input.addEventListener('keydown', (e) => {
|
||||
if(e.key === 'Enter') {
|
||||
const val = input.value.toLowerCase();
|
||||
input.value = '';
|
||||
|
||||
// Visual Feedback
|
||||
document.querySelector('.command-bar').style.boxShadow = "0 0 30px #00ff41";
|
||||
setTimeout(() => document.querySelector('.command-bar').style.boxShadow = "0 0 20px rgba(0, 255, 255, 0.1)", 200);
|
||||
|
||||
// Basic Logic
|
||||
if(val.includes('scan')) {
|
||||
alert('System Scan Initiated... No Threats Found.');
|
||||
} else if (val.includes('shutdown')) {
|
||||
document.body.style.filter = "grayscale(100%)";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- Initialization ---
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
initIntro();
|
||||
initMonitor();
|
||||
initNeuralNet();
|
||||
initHoloCards();
|
||||
initConsole();
|
||||
|
||||
// Timeline interaction
|
||||
document.querySelectorAll('.time-node').forEach(node => {
|
||||
node.addEventListener('click', function() {
|
||||
document.querySelectorAll('.time-node').forEach(n => n.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Visual glitch on city change
|
||||
gsap.to(camera.position, {
|
||||
z: Math.random() * 100 + 50,
|
||||
duration: 1.5,
|
||||
ease: "power2.inOut"
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue