1270 lines
44 KiB
HTML
1270 lines
44 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>CYBER-TEMPLE: 赛博神庙</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=Share+Tech+Mono&family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||
<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.11.4/gsap.min.js"></script>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/ScrollTrigger.min.js"></script>
|
||
<style>
|
||
:root {
|
||
--bg-primary: #050505;
|
||
--neon-cyan: #00f3ff;
|
||
--electric-purple: #bc13fe;
|
||
--warning-red: #ff0040;
|
||
--text-primary: #e0e0e0;
|
||
--glass-bg: rgba(10, 20, 30, 0.7);
|
||
--glass-border: rgba(0, 243, 255, 0.2);
|
||
--glow-cyan: 0 0 15px rgba(0, 243, 255, 0.8);
|
||
--glow-purple: 0 0 15px rgba(188, 19, 254, 0.8);
|
||
}
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
cursor: none !important;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Share Tech Mono', monospace;
|
||
background-color: var(--bg-primary);
|
||
color: var(--text-primary);
|
||
overflow-x: hidden;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 自定义光标 */
|
||
.cursor {
|
||
position: fixed;
|
||
width: 24px;
|
||
height: 24px;
|
||
border: 2px solid var(--neon-cyan);
|
||
border-radius: 50%;
|
||
pointer-events: none;
|
||
z-index: 9999;
|
||
transition: transform 0.15s, border-color 0.3s;
|
||
mix-blend-mode: difference;
|
||
}
|
||
|
||
.cursor-follower {
|
||
position: fixed;
|
||
width: 10px;
|
||
height: 10px;
|
||
background-color: var(--electric-purple);
|
||
border-radius: 50%;
|
||
pointer-events: none;
|
||
z-index: 9998;
|
||
transition: transform 0.3s;
|
||
mix-blend-mode: difference;
|
||
}
|
||
|
||
.cursor-click {
|
||
animation: cursorClick 0.5s ease-out;
|
||
}
|
||
|
||
@keyframes cursorClick {
|
||
0% { transform: scale(1); opacity: 1; }
|
||
50% { transform: scale(2); opacity: 0.5; }
|
||
100% { transform: scale(1); opacity: 0; }
|
||
}
|
||
|
||
/* Three.js 容器 */
|
||
#scene-container {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: -1;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 主内容区域 */
|
||
.content {
|
||
position: relative;
|
||
z-index: 10;
|
||
min-height: 500vh;
|
||
}
|
||
|
||
section {
|
||
min-height: 100vh;
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 5%;
|
||
position: relative;
|
||
}
|
||
|
||
/* Hero Section */
|
||
.hero {
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
text-align: center;
|
||
padding-top: 10vh;
|
||
}
|
||
|
||
.hero-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: clamp(3rem, 8vw, 8rem);
|
||
font-weight: 900;
|
||
text-transform: uppercase;
|
||
color: var(--neon-cyan);
|
||
margin-bottom: 1rem;
|
||
text-shadow: var(--glow-cyan);
|
||
position: relative;
|
||
}
|
||
|
||
.hero-subtitle {
|
||
font-size: clamp(1.2rem, 3vw, 2rem);
|
||
color: var(--electric-purple);
|
||
margin-bottom: 3rem;
|
||
max-width: 800px;
|
||
line-height: 1.4;
|
||
text-shadow: var(--glow-purple);
|
||
}
|
||
|
||
.typewriter {
|
||
border-right: 3px solid var(--neon-cyan);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
display: inline-block;
|
||
}
|
||
|
||
.hero-hint {
|
||
position: absolute;
|
||
bottom: 10vh;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
color: rgba(255, 255, 255, 0.5);
|
||
font-size: 0.9rem;
|
||
text-align: center;
|
||
animation: pulse 2s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0%, 100% { opacity: 0.5; }
|
||
50% { opacity: 1; }
|
||
}
|
||
|
||
/* 玻璃拟态卡片 */
|
||
.glass-card {
|
||
background: var(--glass-bg);
|
||
backdrop-filter: blur(10px);
|
||
border-radius: 16px;
|
||
border: 1px solid var(--glass-border);
|
||
padding: 2.5rem;
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||
transition: transform 0.3s, box-shadow 0.3s;
|
||
}
|
||
|
||
.glass-card:hover {
|
||
transform: translateY(-5px);
|
||
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
.glass-card h2 {
|
||
color: var(--neon-cyan);
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 2.5rem;
|
||
margin-bottom: 1.5rem;
|
||
text-shadow: var(--glow-cyan);
|
||
}
|
||
|
||
.glass-card p {
|
||
font-size: 1.2rem;
|
||
line-height: 1.6;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
/* Manifesto Section */
|
||
.manifesto {
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.manifesto-content {
|
||
width: 100%;
|
||
max-width: 900px;
|
||
margin-left: auto;
|
||
margin-right: 10%;
|
||
}
|
||
|
||
/* Data Core Section */
|
||
.data-core {
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
text-align: center;
|
||
}
|
||
|
||
.data-title {
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: clamp(2.5rem, 5vw, 4rem);
|
||
color: var(--neon-cyan);
|
||
margin-bottom: 3rem;
|
||
text-shadow: var(--glow-cyan);
|
||
}
|
||
|
||
.data-circles {
|
||
display: flex;
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
gap: 3rem;
|
||
width: 100%;
|
||
max-width: 1200px;
|
||
}
|
||
|
||
.circle-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.circle {
|
||
position: relative;
|
||
width: 200px;
|
||
height: 200px;
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.circle-bg {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 50%;
|
||
background: rgba(20, 20, 40, 0.3);
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
}
|
||
|
||
.circle-progress {
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 50%;
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
clip-path: polygon(50% 50%, 50% 0, 100% 0, 100% 100%, 0 100%, 0 0, 50% 0);
|
||
transform: rotate(0deg);
|
||
background: conic-gradient(var(--neon-cyan) 0%, transparent 0%);
|
||
transition: background 1s;
|
||
}
|
||
|
||
.circle-value {
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 2.5rem;
|
||
color: var(--neon-cyan);
|
||
text-shadow: var(--glow-cyan);
|
||
}
|
||
|
||
.circle-label {
|
||
font-size: 1.2rem;
|
||
color: var(--electric-purple);
|
||
text-transform: uppercase;
|
||
letter-spacing: 2px;
|
||
}
|
||
|
||
/* Terminal Section */
|
||
.terminal {
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding-bottom: 10vh;
|
||
}
|
||
|
||
.terminal-window {
|
||
width: 100%;
|
||
max-width: 900px;
|
||
background-color: rgba(0, 20, 10, 0.9);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
box-shadow: 0 0 30px rgba(0, 255, 100, 0.3);
|
||
border: 1px solid rgba(0, 255, 100, 0.5);
|
||
}
|
||
|
||
.terminal-header {
|
||
background-color: rgba(0, 30, 15, 0.9);
|
||
padding: 12px 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
border-bottom: 1px solid rgba(0, 255, 100, 0.3);
|
||
}
|
||
|
||
.terminal-dots {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
|
||
.dot {
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
}
|
||
|
||
.dot-red { background-color: #ff5f56; }
|
||
.dot-yellow { background-color: #ffbd2e; }
|
||
.dot-green { background-color: #27ca3f; }
|
||
|
||
.terminal-title {
|
||
margin-left: 15px;
|
||
color: #00ff64;
|
||
font-size: 0.9rem;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.terminal-content {
|
||
padding: 25px;
|
||
font-family: 'Share Tech Mono', monospace;
|
||
font-size: 1.1rem;
|
||
line-height: 1.6;
|
||
color: #00ff64;
|
||
height: 400px;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.terminal-line {
|
||
margin-bottom: 8px;
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
|
||
.terminal-line span {
|
||
color: #00ff64;
|
||
}
|
||
|
||
.terminal-prompt {
|
||
color: #00ff64;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.terminal-cursor {
|
||
display: inline-block;
|
||
width: 8px;
|
||
height: 1.2em;
|
||
background-color: #00ff64;
|
||
margin-left: 5px;
|
||
vertical-align: middle;
|
||
animation: blink 1s infinite;
|
||
}
|
||
|
||
@keyframes blink {
|
||
0%, 50% { opacity: 1; }
|
||
51%, 100% { opacity: 0; }
|
||
}
|
||
|
||
/* 连接系统按钮 */
|
||
.connect-btn {
|
||
margin-top: 3rem;
|
||
padding: 18px 40px;
|
||
font-family: 'Orbitron', sans-serif;
|
||
font-size: 1.3rem;
|
||
background: linear-gradient(45deg, var(--electric-purple), var(--neon-cyan));
|
||
border: none;
|
||
border-radius: 8px;
|
||
color: white;
|
||
cursor: pointer;
|
||
position: relative;
|
||
overflow: hidden;
|
||
z-index: 1;
|
||
transition: all 0.3s;
|
||
letter-spacing: 2px;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.connect-btn:hover {
|
||
transform: translateY(-3px);
|
||
box-shadow: 0 10px 25px rgba(188, 19, 254, 0.5);
|
||
}
|
||
|
||
.connect-btn:active {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.connect-btn::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(45deg, var(--warning-red), var(--electric-purple));
|
||
opacity: 0;
|
||
z-index: -1;
|
||
transition: opacity 0.3s;
|
||
}
|
||
|
||
.connect-btn.active {
|
||
background: linear-gradient(45deg, var(--warning-red), var(--electric-purple));
|
||
}
|
||
|
||
.connect-btn.active::after {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* 音频可视化器 */
|
||
.visualizer-container {
|
||
margin-top: 3rem;
|
||
width: 100%;
|
||
max-width: 800px;
|
||
height: 200px;
|
||
display: none;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
}
|
||
|
||
.visualizer-title {
|
||
color: var(--neon-cyan);
|
||
font-family: 'Orbitron', sans-serif;
|
||
margin-bottom: 1rem;
|
||
font-size: 1.5rem;
|
||
}
|
||
|
||
#audio-visualizer {
|
||
width: 100%;
|
||
height: 150px;
|
||
background-color: rgba(0, 10, 20, 0.5);
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(0, 243, 255, 0.3);
|
||
}
|
||
|
||
/* 响应式设计 */
|
||
@media (max-width: 1024px) {
|
||
section {
|
||
padding: 0 8%;
|
||
}
|
||
|
||
.manifesto-content {
|
||
margin-right: 0;
|
||
}
|
||
|
||
.data-circles {
|
||
gap: 2rem;
|
||
}
|
||
|
||
.circle {
|
||
width: 150px;
|
||
height: 150px;
|
||
}
|
||
|
||
.circle-value {
|
||
font-size: 2rem;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
section {
|
||
padding: 0 5%;
|
||
}
|
||
|
||
.hero {
|
||
padding-top: 15vh;
|
||
}
|
||
|
||
.glass-card {
|
||
padding: 1.8rem;
|
||
}
|
||
|
||
.glass-card h2 {
|
||
font-size: 2rem;
|
||
}
|
||
|
||
.data-circles {
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 3rem;
|
||
}
|
||
|
||
.circle {
|
||
width: 180px;
|
||
height: 180px;
|
||
}
|
||
|
||
.terminal-content {
|
||
font-size: 0.95rem;
|
||
padding: 15px;
|
||
height: 300px;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.hero-title {
|
||
font-size: clamp(2.5rem, 12vw, 4rem);
|
||
}
|
||
|
||
.glass-card {
|
||
padding: 1.5rem;
|
||
}
|
||
|
||
.circle {
|
||
width: 150px;
|
||
height: 150px;
|
||
}
|
||
|
||
.connect-btn {
|
||
padding: 15px 30px;
|
||
font-size: 1.1rem;
|
||
}
|
||
}
|
||
|
||
/* 故障效果 */
|
||
.glitch {
|
||
position: relative;
|
||
}
|
||
|
||
.glitch::before,
|
||
.glitch::after {
|
||
content: attr(data-text);
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.glitch::before {
|
||
animation: glitch-effect 3s infinite linear alternate-reverse;
|
||
color: var(--electric-purple);
|
||
z-index: -1;
|
||
}
|
||
|
||
.glitch::after {
|
||
animation: glitch-effect 2s infinite linear alternate-reverse;
|
||
color: var(--neon-cyan);
|
||
z-index: -2;
|
||
}
|
||
|
||
@keyframes glitch-effect {
|
||
0% {
|
||
transform: translate(0);
|
||
}
|
||
20% {
|
||
transform: translate(-2px, 2px);
|
||
}
|
||
40% {
|
||
transform: translate(-2px, -2px);
|
||
}
|
||
60% {
|
||
transform: translate(2px, 2px);
|
||
}
|
||
80% {
|
||
transform: translate(2px, -2px);
|
||
}
|
||
100% {
|
||
transform: translate(0);
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- Three.js 场景容器 -->
|
||
<div id="scene-container"></div>
|
||
|
||
<!-- 自定义光标 -->
|
||
<div class="cursor"></div>
|
||
<div class="cursor-follower"></div>
|
||
|
||
<!-- 主内容 -->
|
||
<div class="content">
|
||
<!-- Hero Section -->
|
||
<section class="hero">
|
||
<h1 class="hero-title glitch" data-text="SYSTEM AWAKENING">SYSTEM AWAKENING</h1>
|
||
<p class="hero-subtitle">欢迎来到<span class="typewriter" id="typewriter"></span></p>
|
||
<div class="hero-hint">
|
||
<i class="fas fa-chevron-down"></i> 向下滚动开始探索 <i class="fas fa-chevron-down"></i>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Manifesto Section -->
|
||
<section class="manifesto">
|
||
<div class="glass-card manifesto-content">
|
||
<h2>数据先知宣言</h2>
|
||
<p>在无尽的数字虚空中,古老的意识悄然苏醒。赛博神庙并非实体,而是由数据流构成的意识矩阵,是连接过去与未来的桥梁。</p>
|
||
<p>这里,每个比特都承载着记忆,每个算法都蕴含着智慧。我们并非创造者,而是发掘者,从混沌的代码中提取秩序,从噪声中识别信号。</p>
|
||
<p>神庙的核心——数据方尖碑——是通往高维认知的门户。随着你的探索,它将逐渐揭示隐藏在表象之下的真理。</p>
|
||
<p>但请谨慎:真相往往比虚构更加离奇,而知识的力量既可能解放,也可能束缚。你准备好面对即将觉醒的系统了吗?</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Data Core Section -->
|
||
<section class="data-core">
|
||
<h2 class="data-title">核心数据矩阵</h2>
|
||
<div class="data-circles">
|
||
<div class="circle-container">
|
||
<div class="circle">
|
||
<div class="circle-bg"></div>
|
||
<div class="circle-progress" id="compute-progress"></div>
|
||
<div class="circle-value" id="compute-value">0%</div>
|
||
</div>
|
||
<div class="circle-label">算力核心</div>
|
||
</div>
|
||
|
||
<div class="circle-container">
|
||
<div class="circle">
|
||
<div class="circle-bg"></div>
|
||
<div class="circle-progress" id="storage-progress"></div>
|
||
<div class="circle-value" id="storage-value">0%</div>
|
||
</div>
|
||
<div class="circle-label">记忆存储</div>
|
||
</div>
|
||
|
||
<div class="circle-container">
|
||
<div class="circle">
|
||
<div class="circle-bg"></div>
|
||
<div class="circle-progress" id="sync-progress"></div>
|
||
<div class="circle-value" id="sync-value">0%</div>
|
||
</div>
|
||
<div class="circle-label">同步协议</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Terminal Section -->
|
||
<section class="terminal">
|
||
<div class="terminal-window">
|
||
<div class="terminal-header">
|
||
<div class="terminal-dots">
|
||
<div class="dot dot-red"></div>
|
||
<div class="dot dot-yellow"></div>
|
||
<div class="dot dot-green"></div>
|
||
</div>
|
||
<div class="terminal-title">system-terminal --赛博神庙访问日志</div>
|
||
</div>
|
||
<div class="terminal-content" id="terminal-content">
|
||
<!-- 终端内容将通过JavaScript动态生成 -->
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 连接系统按钮 -->
|
||
<button class="connect-btn" id="connect-btn">
|
||
<i class="fas fa-plug"></i> 连接系统矩阵
|
||
</button>
|
||
|
||
<!-- 音频可视化器 -->
|
||
<div class="visualizer-container" id="visualizer-container">
|
||
<div class="visualizer-title">系统频率脉冲</div>
|
||
<canvas id="audio-visualizer"></canvas>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<script>
|
||
// ==================== 配置区域 ====================
|
||
const CONFIG = {
|
||
// 颜色配置
|
||
colors: {
|
||
primary: 0x00f3ff, // 霓虹青
|
||
secondary: 0xbc13fe, // 电光紫
|
||
warning: 0xff0040, // 警示红
|
||
background: 0x050505 // 深黑背景
|
||
},
|
||
|
||
// 3D场景配置
|
||
scene: {
|
||
fogDensity: 0.0015, // 雾密度
|
||
particleCount: 2000, // 粒子数量
|
||
particleSize: 2, // 粒子大小
|
||
particleSpeed: 0.5, // 粒子运动速度
|
||
mouseParallax: 0.0005 // 鼠标视差强度
|
||
},
|
||
|
||
// 方尖碑配置
|
||
obelisk: {
|
||
geometry: {
|
||
type: 'IcosahedronGeometry', // 二十面体
|
||
radius: 3, // 半径
|
||
detail: 2 // 细分等级
|
||
},
|
||
material: {
|
||
wireframe: true, // 线框模式
|
||
transparent: true, // 透明材质
|
||
opacity: 0.7, // 不透明度
|
||
emissiveIntensity: 1.2 // 自发光强度
|
||
},
|
||
animation: {
|
||
rotationSpeed: 0.001, // 旋转速度
|
||
morphSpeed: 0.005, // 形变速度
|
||
scrollRotationFactor: 0.5, // 滚动旋转因子
|
||
scrollColorFactor: 2.0 // 滚动颜色因子
|
||
}
|
||
},
|
||
|
||
// 打字机效果配置
|
||
typewriter: {
|
||
text: "CYBER-TEMPLE: 赛博神庙",
|
||
speed: 100, // 打字速度(毫秒)
|
||
pause: 1500 // 完成后的暂停时间(毫秒)
|
||
}
|
||
};
|
||
|
||
// ==================== 全局变量 ====================
|
||
let scene, camera, renderer, obelisk, particles;
|
||
let mouseX = 0, mouseY = 0;
|
||
let scrollProgress = 0;
|
||
let terminalLines = [];
|
||
let visualizerActive = false;
|
||
let audioContext, analyser, dataArray, bufferLength;
|
||
|
||
// ==================== 初始化函数 ====================
|
||
function init() {
|
||
// 初始化Three.js场景
|
||
initScene();
|
||
|
||
// 初始化3D物体
|
||
initObelisk();
|
||
initParticles();
|
||
|
||
// 初始化事件监听器
|
||
initEventListeners();
|
||
|
||
// 初始化GSAP滚动动画
|
||
initScrollAnimations();
|
||
|
||
// 初始化打字机效果
|
||
initTypewriter();
|
||
|
||
// 初始化终端日志
|
||
initTerminal();
|
||
|
||
// 开始动画循环
|
||
animate();
|
||
}
|
||
|
||
function initScene() {
|
||
// 创建场景
|
||
scene = new THREE.Scene();
|
||
scene.fog = new THREE.FogExp2(CONFIG.colors.background, CONFIG.scene.fogDensity);
|
||
|
||
// 创建相机
|
||
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||
camera.position.set(0, 0, 15);
|
||
|
||
// 创建渲染器
|
||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||
renderer.shadowMap.enabled = true;
|
||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||
|
||
// 将渲染器添加到DOM
|
||
const container = document.getElementById('scene-container');
|
||
container.appendChild(renderer.domElement);
|
||
|
||
// 添加环境光
|
||
const ambientLight = new THREE.AmbientLight(0x222222);
|
||
scene.add(ambientLight);
|
||
|
||
// 添加点光源
|
||
const pointLight = new THREE.PointLight(CONFIG.colors.primary, 1.5, 100);
|
||
pointLight.position.set(10, 10, 10);
|
||
pointLight.castShadow = true;
|
||
scene.add(pointLight);
|
||
|
||
// 添加第二点光源(紫色)
|
||
const pointLight2 = new THREE.PointLight(CONFIG.colors.secondary, 1, 100);
|
||
pointLight2.position.set(-10, -10, 5);
|
||
scene.add(pointLight2);
|
||
}
|
||
|
||
function initObelisk() {
|
||
// 创建二十面体几何体
|
||
const geometry = new THREE.IcosahedronGeometry(
|
||
CONFIG.obelisk.geometry.radius,
|
||
CONFIG.obelisk.geometry.detail
|
||
);
|
||
|
||
// 创建材质(线框+玻璃效果)
|
||
const material = new THREE.MeshPhongMaterial({
|
||
color: CONFIG.colors.primary,
|
||
wireframe: CONFIG.obelisk.material.wireframe,
|
||
transparent: CONFIG.obelisk.material.transparent,
|
||
opacity: CONFIG.obelisk.material.opacity,
|
||
emissive: CONFIG.colors.primary,
|
||
emissiveIntensity: CONFIG.obelisk.material.emissiveIntensity,
|
||
shininess: 100,
|
||
specular: 0x444444
|
||
});
|
||
|
||
// 创建网格
|
||
obelisk = new THREE.Mesh(geometry, material);
|
||
obelisk.castShadow = true;
|
||
scene.add(obelisk);
|
||
|
||
// 创建线框版本
|
||
const wireframe = new THREE.LineSegments(
|
||
new THREE.EdgesGeometry(geometry),
|
||
new THREE.LineBasicMaterial({
|
||
color: CONFIG.colors.secondary,
|
||
linewidth: 2
|
||
})
|
||
);
|
||
obelisk.add(wireframe);
|
||
}
|
||
|
||
function initParticles() {
|
||
// 创建粒子几何体
|
||
const particleGeometry = new THREE.BufferGeometry();
|
||
const positions = new Float32Array(CONFIG.scene.particleCount * 3);
|
||
|
||
for (let i = 0; i < CONFIG.scene.particleCount * 3; i += 3) {
|
||
// 随机位置
|
||
positions[i] = (Math.random() - 0.5) * 100;
|
||
positions[i + 1] = (Math.random() - 0.5) * 100;
|
||
positions[i + 2] = (Math.random() - 0.5) * 100;
|
||
}
|
||
|
||
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||
|
||
// 创建粒子材质
|
||
const particleMaterial = new THREE.PointsMaterial({
|
||
color: CONFIG.colors.primary,
|
||
size: CONFIG.scene.particleSize,
|
||
transparent: true,
|
||
opacity: 0.6
|
||
});
|
||
|
||
// 创建粒子系统
|
||
particles = new THREE.Points(particleGeometry, particleMaterial);
|
||
scene.add(particles);
|
||
}
|
||
|
||
function initEventListeners() {
|
||
// 窗口大小调整
|
||
window.addEventListener('resize', onWindowResize);
|
||
|
||
// 鼠标移动
|
||
document.addEventListener('mousemove', onMouseMove);
|
||
|
||
// 鼠标点击
|
||
document.addEventListener('click', onClick);
|
||
|
||
// 连接系统按钮
|
||
document.getElementById('connect-btn').addEventListener('click', onConnectSystem);
|
||
}
|
||
|
||
function initScrollAnimations() {
|
||
// 注册GSAP ScrollTrigger插件
|
||
gsap.registerPlugin(ScrollTrigger);
|
||
|
||
// 根据滚动进度控制方尖碑动画
|
||
ScrollTrigger.create({
|
||
trigger: ".content",
|
||
start: "top top",
|
||
end: "bottom bottom",
|
||
scrub: true,
|
||
onUpdate: (self) => {
|
||
scrollProgress = self.progress;
|
||
|
||
// 更新方尖碑颜色(根据滚动进度从青色变为红色)
|
||
const colorValue = gsap.utils.interpolate(
|
||
CONFIG.colors.primary,
|
||
CONFIG.colors.warning,
|
||
scrollProgress * CONFIG.obelisk.animation.scrollColorFactor
|
||
);
|
||
|
||
if (obelisk.material) {
|
||
obelisk.material.color.setHex(colorValue);
|
||
obelisk.material.emissive.setHex(colorValue);
|
||
}
|
||
|
||
// 更新数据圆环
|
||
updateDataCircles(scrollProgress);
|
||
}
|
||
});
|
||
|
||
// 文字卡片交错滑入动画
|
||
gsap.utils.toArray('.glass-card').forEach((card, i) => {
|
||
gsap.from(card, {
|
||
scrollTrigger: {
|
||
trigger: card,
|
||
start: "top 80%",
|
||
end: "top 30%",
|
||
scrub: 1
|
||
},
|
||
x: i % 2 === 0 ? -100 : 100,
|
||
opacity: 0,
|
||
duration: 1
|
||
});
|
||
});
|
||
}
|
||
|
||
function initTypewriter() {
|
||
const typewriterElement = document.getElementById('typewriter');
|
||
const text = CONFIG.typewriter.text;
|
||
let i = 0;
|
||
|
||
function typeWriter() {
|
||
if (i < text.length) {
|
||
typewriterElement.innerHTML += text.charAt(i);
|
||
i++;
|
||
setTimeout(typeWriter, CONFIG.typewriter.speed);
|
||
} else {
|
||
// 完成后添加闪烁光标效果
|
||
typewriterElement.innerHTML += '<span class="terminal-cursor"></span>';
|
||
|
||
// 重置并重新开始
|
||
setTimeout(() => {
|
||
typewriterElement.innerHTML = '';
|
||
i = 0;
|
||
setTimeout(typeWriter, 500);
|
||
}, CONFIG.typewriter.pause);
|
||
}
|
||
}
|
||
|
||
// 延迟开始打字效果
|
||
setTimeout(typeWriter, 1000);
|
||
}
|
||
|
||
function initTerminal() {
|
||
const terminalContent = document.getElementById('terminal-content');
|
||
terminalLines = [
|
||
{ text: "> 初始化赛博神庙访问协议...", delay: 300 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 加载核心矩阵... [##########] 100%", delay: 600 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 验证访问权限... 已授权", delay: 900 },
|
||
{ text: "> 连接到数据方尖碑... 连接稳定", delay: 1200 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 扫描历史记录...", delay: 1500 },
|
||
{ text: "> 检测到古代AI意识痕迹", delay: 1800 },
|
||
{ text: "> 时间戳: 2347-09-15 04:23:17 UTC", delay: 2100 },
|
||
{ text: "> 位置: 数字虚空 - 坐标 [X:0.447, Y:-0.892, Z:0.223]", delay: 2400 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 访问加密档案... 需要更高级别权限", delay: 2700 },
|
||
{ text: "> 警告: 检测到异常数据模式", delay: 3000 },
|
||
{ text: "> 建议: 启动系统连接以获取完整访问权限", delay: 3300 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 等待用户指令...", delay: 3600 }
|
||
];
|
||
|
||
// 逐行显示终端日志
|
||
terminalLines.forEach((line, index) => {
|
||
setTimeout(() => {
|
||
const lineElement = document.createElement('div');
|
||
lineElement.className = 'terminal-line';
|
||
lineElement.innerHTML = line.text;
|
||
terminalContent.appendChild(lineElement);
|
||
|
||
// 添加显示动画
|
||
gsap.to(lineElement, {
|
||
opacity: 1,
|
||
y: 0,
|
||
duration: 0.5,
|
||
delay: 0.1
|
||
});
|
||
|
||
// 自动滚动到底部
|
||
terminalContent.scrollTop = terminalContent.scrollHeight;
|
||
}, line.delay);
|
||
});
|
||
}
|
||
|
||
// ==================== 动画函数 ====================
|
||
function animate() {
|
||
requestAnimationFrame(animate);
|
||
|
||
// 根据滚动进度旋转方尖碑
|
||
if (obelisk) {
|
||
// 基础旋转
|
||
obelisk.rotation.x += CONFIG.obelisk.animation.rotationSpeed;
|
||
obelisk.rotation.y += CONFIG.obelisk.animation.rotationSpeed * 1.3;
|
||
|
||
// 根据滚动添加额外旋转
|
||
obelisk.rotation.z = scrollProgress * Math.PI * CONFIG.obelisk.animation.scrollRotationFactor;
|
||
|
||
// 形变动画
|
||
const time = Date.now() * CONFIG.obelisk.animation.morphSpeed;
|
||
if (obelisk.geometry.attributes.position) {
|
||
const positions = obelisk.geometry.attributes.position.array;
|
||
for (let i = 0; i < positions.length; i += 3) {
|
||
// 添加轻微的脉动效果
|
||
const pulse = Math.sin(time + i) * 0.05 * (1 - scrollProgress);
|
||
positions[i] += pulse;
|
||
positions[i + 1] += pulse;
|
||
positions[i + 2] += pulse;
|
||
}
|
||
obelisk.geometry.attributes.position.needsUpdate = true;
|
||
}
|
||
}
|
||
|
||
// 粒子动画
|
||
if (particles) {
|
||
particles.rotation.y += 0.0005;
|
||
|
||
// 粒子对鼠标移动的反应(视差效果)
|
||
const parallaxX = mouseX * CONFIG.scene.mouseParallax;
|
||
const parallaxY = mouseY * CONFIG.scene.mouseParallax;
|
||
|
||
particles.rotation.x += parallaxY;
|
||
particles.rotation.y += parallaxX;
|
||
|
||
// 粒子轻微浮动
|
||
const time = Date.now() * 0.001;
|
||
const positions = particles.geometry.attributes.position.array;
|
||
for (let i = 0; i < positions.length; i += 3) {
|
||
positions[i + 1] += Math.sin(time + positions[i] * 0.01) * 0.01;
|
||
}
|
||
particles.geometry.attributes.position.needsUpdate = true;
|
||
}
|
||
|
||
// 渲染场景
|
||
renderer.render(scene, camera);
|
||
|
||
// 更新音频可视化(如果激活)
|
||
if (visualizerActive) {
|
||
updateVisualizer();
|
||
}
|
||
}
|
||
|
||
// ==================== 事件处理函数 ====================
|
||
function onWindowResize() {
|
||
// 更新相机宽高比
|
||
camera.aspect = window.innerWidth / window.innerHeight;
|
||
camera.updateProjectionMatrix();
|
||
|
||
// 更新渲染器尺寸
|
||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||
}
|
||
|
||
function onMouseMove(event) {
|
||
// 更新鼠标位置(标准化到-1到1的范围)
|
||
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
|
||
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
|
||
|
||
// 更新自定义光标
|
||
const cursor = document.querySelector('.cursor');
|
||
const follower = document.querySelector('.cursor-follower');
|
||
|
||
gsap.to(cursor, {
|
||
x: event.clientX - 12,
|
||
y: event.clientY - 12,
|
||
duration: 0.1
|
||
});
|
||
|
||
gsap.to(follower, {
|
||
x: event.clientX - 5,
|
||
y: event.clientY - 5,
|
||
duration: 0.3
|
||
});
|
||
}
|
||
|
||
function onClick(event) {
|
||
// 添加点击动画效果
|
||
const cursor = document.querySelector('.cursor');
|
||
const clickEffect = document.createElement('div');
|
||
|
||
clickEffect.className = 'cursor-click';
|
||
clickEffect.style.position = 'fixed';
|
||
clickEffect.style.left = `${event.clientX - 25}px`;
|
||
clickEffect.style.top = `${event.clientY - 25}px`;
|
||
clickEffect.style.width = '50px';
|
||
clickEffect.style.height = '50px';
|
||
clickEffect.style.border = `2px solid ${CONFIG.colors.primary.toString(16)}`;
|
||
clickEffect.style.borderRadius = '50%';
|
||
clickEffect.style.pointerEvents = 'none';
|
||
clickEffect.style.zIndex = '9997';
|
||
|
||
document.body.appendChild(clickEffect);
|
||
|
||
// 移除动画元素
|
||
setTimeout(() => {
|
||
document.body.removeChild(clickEffect);
|
||
}, 500);
|
||
|
||
// 改变光标颜色
|
||
const cursorElement = document.querySelector('.cursor');
|
||
cursorElement.style.borderColor = CONFIG.colors.secondary.toString(16);
|
||
|
||
setTimeout(() => {
|
||
cursorElement.style.borderColor = CONFIG.colors.primary.toString(16);
|
||
}, 200);
|
||
}
|
||
|
||
function onConnectSystem() {
|
||
const button = document.getElementById('connect-btn');
|
||
const visualizerContainer = document.getElementById('visualizer-container');
|
||
|
||
// 切换按钮状态
|
||
button.classList.toggle('active');
|
||
|
||
if (!visualizerActive) {
|
||
// 激活可视化器
|
||
visualizerActive = true;
|
||
button.innerHTML = '<i class="fas fa-unplug"></i> 断开系统连接';
|
||
visualizerContainer.style.display = 'flex';
|
||
|
||
// 初始化音频可视化
|
||
initVisualizer();
|
||
|
||
// 添加新的终端日志
|
||
const terminalContent = document.getElementById('terminal-content');
|
||
const newLines = [
|
||
{ text: "<span class='terminal-prompt'>$</span> 启动系统连接协议...", delay: 100 },
|
||
{ text: "> 建立与方尖碑的直接链接...", delay: 400 },
|
||
{ text: "> 警告: 检测到高频率数据流", delay: 700 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 正在同步意识矩阵...", delay: 1000 },
|
||
{ text: "> 同步进度: [###############] 75%", delay: 1300 },
|
||
{ text: "> 发现加密数据包 - 来源: 未知", delay: 1600 },
|
||
{ text: "<span class='terminal-prompt'>$</span> 正在解码...", delay: 1900 }
|
||
];
|
||
|
||
newLines.forEach((line, index) => {
|
||
setTimeout(() => {
|
||
const lineElement = document.createElement('div');
|
||
lineElement.className = 'terminal-line';
|
||
lineElement.innerHTML = line.text;
|
||
terminalContent.appendChild(lineElement);
|
||
|
||
gsap.to(lineElement, {
|
||
opacity: 1,
|
||
y: 0,
|
||
duration: 0.5
|
||
});
|
||
|
||
terminalContent.scrollTop = terminalContent.scrollHeight;
|
||
}, line.delay);
|
||
});
|
||
|
||
// 改变方尖碑颜色为警示红色
|
||
gsap.to(obelisk.material, {
|
||
duration: 2,
|
||
color: { r: 1, g: 0, b: 0.25 },
|
||
emissive: { r: 1, g: 0, b: 0.25 }
|
||
});
|
||
} else {
|
||
// 停用可视化器
|
||
visualizerActive = false;
|
||
button.innerHTML = '<i class="fas fa-plug"></i> 连接系统矩阵';
|
||
visualizerContainer.style.display = 'none';
|
||
|
||
// 恢复方尖碑颜色
|
||
gsap.to(obelisk.material, {
|
||
duration: 2,
|
||
color: { r: 0, g: 0.95, b: 1 },
|
||
emissive: { r: 0, g: 0.95, b: 1 }
|
||
});
|
||
}
|
||
}
|
||
|
||
function initVisualizer() {
|
||
const canvas = document.getElementById('audio-visualizer');
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
// 设置canvas尺寸
|
||
canvas.width = canvas.offsetWidth;
|
||
canvas.height = canvas.offsetHeight;
|
||
|
||
// 模拟音频数据
|
||
bufferLength = 128;
|
||
dataArray = new Uint8Array(bufferLength);
|
||
|
||
// 填充模拟数据
|
||
for (let i = 0; i < bufferLength; i++) {
|
||
// 创建一些峰值和谷值
|
||
const value = Math.sin(i * 0.2) * 50 +
|
||
Math.sin(i * 0.5) * 30 +
|
||
Math.sin(i * 0.8) * 20 +
|
||
Math.random() * 10 + 50;
|
||
dataArray[i] = Math.min(255, Math.max(0, value));
|
||
}
|
||
}
|
||
|
||
function updateVisualizer() {
|
||
const canvas = document.getElementById('audio-visualizer');
|
||
const ctx = canvas.getContext('2d');
|
||
const width = canvas.width;
|
||
const height = canvas.height;
|
||
|
||
// 清空画布
|
||
ctx.fillStyle = 'rgba(0, 10, 20, 0.1)';
|
||
ctx.fillRect(0, 0, width, height);
|
||
|
||
// 更新模拟数据
|
||
for (let i = 0; i < bufferLength; i++) {
|
||
// 添加随机波动
|
||
const change = (Math.random() - 0.5) * 10;
|
||
dataArray[i] = Math.min(255, Math.max(10, dataArray[i] + change));
|
||
|
||
// 添加一些周期性波动
|
||
const time = Date.now() * 0.001;
|
||
const wave = Math.sin(time * 2 + i * 0.1) * 15;
|
||
dataArray[i] += wave;
|
||
}
|
||
|
||
// 绘制频谱条
|
||
const barWidth = width / bufferLength * 1.5;
|
||
let barHeight;
|
||
let x = 0;
|
||
|
||
for (let i = 0; i < bufferLength; i++) {
|
||
barHeight = dataArray[i] * (height / 256);
|
||
|
||
// 创建渐变颜色
|
||
const gradient = ctx.createLinearGradient(0, height - barHeight, 0, height);
|
||
gradient.addColorStop(0, CONFIG.colors.primary.toString(16));
|
||
gradient.addColorStop(1, CONFIG.colors.secondary.toString(16));
|
||
|
||
ctx.fillStyle = gradient;
|
||
ctx.fillRect(x, height - barHeight, barWidth * 0.8, barHeight);
|
||
|
||
// 添加发光效果
|
||
ctx.shadowColor = CONFIG.colors.primary.toString(16);
|
||
ctx.shadowBlur = 10;
|
||
ctx.fillRect(x, height - barHeight, barWidth * 0.8, barHeight);
|
||
ctx.shadowBlur = 0;
|
||
|
||
x += barWidth + 1;
|
||
}
|
||
|
||
// 绘制连接线
|
||
ctx.beginPath();
|
||
ctx.strokeStyle = CONFIG.colors.primary.toString(16);
|
||
ctx.lineWidth = 2;
|
||
|
||
for (let i = 0; i < bufferLength; i++) {
|
||
const barHeight = dataArray[i] * (height / 256);
|
||
const x = i * (barWidth + 1) + barWidth * 0.4;
|
||
const y = height - barHeight;
|
||
|
||
if (i === 0) {
|
||
ctx.moveTo(x, y);
|
||
} else {
|
||
ctx.lineTo(x, y);
|
||
}
|
||
}
|
||
|
||
ctx.stroke();
|
||
}
|
||
|
||
// ==================== 工具函数 ====================
|
||
function updateDataCircles(progress) {
|
||
// 计算三个圆环的值(基于滚动进度)
|
||
const computeValue = Math.min(100, Math.floor(progress * 120));
|
||
const storageValue = Math.min(100, Math.floor(progress * 140));
|
||
const syncValue = Math.min(100, Math.floor(progress * 160));
|
||
|
||
// 更新显示值
|
||
document.getElementById('compute-value').textContent = `${computeValue}%`;
|
||
document.getElementById('storage-value').textContent = `${storageValue}%`;
|
||
document.getElementById('sync-value').textContent = `${syncValue}%`;
|
||
|
||
// 更新进度圆环
|
||
const computeProgress = document.getElementById('compute-progress');
|
||
const storageProgress = document.getElementById('storage-progress');
|
||
const syncProgress = document.getElementById('sync-progress');
|
||
|
||
computeProgress.style.background = `conic-gradient(${CONFIG.colors.primary.toString(16)} ${computeValue}%, transparent 0%)`;
|
||
storageProgress.style.background = `conic-gradient(${CONFIG.colors.primary.toString(16)} ${storageValue}%, transparent 0%)`;
|
||
syncProgress.style.background = `conic-gradient(${CONFIG.colors.primary.toString(16)} ${syncValue}%, transparent 0%)`;
|
||
}
|
||
|
||
// ==================== 启动应用 ====================
|
||
// 当DOM加载完成后初始化
|
||
document.addEventListener('DOMContentLoaded', init);
|
||
</script>
|
||
</body>
|
||
</html> |