LLM-test/test/code/1/glm4.7-web.html

801 lines
29 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>
<!-- 引入 Three.js 和 GSAP -->
<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>
<style>
/* =========================================
1. 全局设置
========================================= */
:root {
--bg-color: #050505;
--neon-cyan: #00f3ff;
--neon-purple: #bc13fe;
--warning-red: #ff003c;
--text-color: #e0e0e0;
--glass-bg: rgba(255, 255, 255, 0.03);
--glass-border: rgba(255, 255, 255, 0.1);
--font-main: 'Courier New', Courier, monospace; /* 单宽字体符合风格 */
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
cursor: none; /* 隐藏默认光标 */
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
overflow-x: hidden;
overscroll-behavior: none;
}
/* 自定义光标样式 */
#cursor {
position: fixed;
top: 0;
left: 0;
width: 20px;
height: 20px;
border: 2px solid var(--neon-cyan);
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 9999;
mix-blend-mode: difference;
transition: width 0.2s, height 0.2s, background-color 0.2s;
}
#cursor.hovered {
width: 50px;
height: 50px;
background-color: rgba(0, 243, 255, 0.1);
border-color: var(--neon-purple);
}
#cursor.click-anim::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
border: 1px solid var(--neon-cyan);
border-radius: 50%;
transform: translate(-50%, -50%);
animation: ripple 0.5s ease-out forwards;
}
@keyframes ripple {
0% { width: 100%; height: 100%; opacity: 1; }
100% { width: 300%; height: 300%; opacity: 0; }
}
/* 3D 画布容器 */
#canvas-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: -1;
/* 径向渐变背景,增强深邃感 */
background: radial-gradient(circle at center, #1a1a1a 0%, #000000 100%);
}
/* =========================================
2. UI 组件与排版
========================================= */
section {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
padding: 2rem;
pointer-events: none; /* 让鼠标事件穿透到 3D 层,但在交互元素上恢复 */
}
/* 允许交互的 UI 元素 */
.interactive {
pointer-events: auto;
}
/* 玻璃拟态卡片 */
.glass-panel {
background: var(--glass-bg);
backdrop-filter: blur(10px);
border: 1px solid var(--glass-border);
padding: 2rem;
border-radius: 8px;
position: relative;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
transition: transform 0.3s ease, border-color 0.3s ease;
}
.glass-panel:hover {
border-color: var(--neon-cyan);
}
/* 装饰性 HUD 角标 */
.glass-panel::before, .glass-panel::after {
content: '';
position: absolute;
width: 10px;
height: 10px;
border: 2px solid var(--neon-cyan);
transition: all 0.3s ease;
}
.glass-panel::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
.glass-panel::after { bottom: -1px; right: -1px; border-left: none; border-top: none; }
h1, h2 {
text-transform: uppercase;
letter-spacing: 4px;
margin-bottom: 1rem;
position: relative;
display: inline-block;
}
h1 {
font-size: clamp(3rem, 8vw, 6rem);
color: #fff;
text-shadow: 2px 2px 0px var(--neon-purple);
}
h2 {
font-size: 2rem;
color: var(--neon-cyan);
border-bottom: 1px solid var(--neon-cyan);
padding-bottom: 0.5rem;
}
p {
line-height: 1.6;
font-size: 1.1rem;
color: #ccc;
margin-bottom: 1rem;
}
/* =========================================
3. 特效样式
========================================= */
/* 故障文字效果 */
.glitch-text {
position: relative;
}
.glitch-text::before, .glitch-text::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--bg-color);
}
.glitch-text::before {
left: 2px;
text-shadow: -1px 0 var(--warning-red);
clip-path: inset(44% 0 61% 0);
animation: glitch-anim-1 2.5s infinite linear alternate-reverse;
}
.glitch-text::after {
left: -2px;
text-shadow: -1px 0 var(--neon-cyan);
clip-path: inset(54% 0 20% 0);
animation: glitch-anim-2 3s infinite linear alternate-reverse;
}
@keyframes glitch-anim-1 {
0% { clip-path: inset(20% 0 80% 0); }
20% { clip-path: inset(60% 0 10% 0); }
40% { clip-path: inset(40% 0 50% 0); }
60% { clip-path: inset(80% 0 5% 0); }
80% { clip-path: inset(10% 0 70% 0); }
100% { clip-path: inset(30% 0 20% 0); }
}
@keyframes glitch-anim-2 {
0% { clip-path: inset(10% 0 60% 0); }
20% { clip-path: inset(80% 0 5% 0); }
40% { clip-path: inset(30% 0 20% 0); }
60% { clip-path: inset(10% 0 80% 0); }
80% { clip-path: inset(50% 0 10% 0); }
100% { clip-path: inset(20% 0 50% 0); }
}
/* 模拟音频频谱 */
.audio-visualizer {
display: flex;
align-items: flex-end;
gap: 4px;
height: 40px;
margin-top: 10px;
}
.bar {
width: 6px;
background: var(--neon-cyan);
height: 5px;
transition: height 0.1s ease;
}
.audio-active .bar {
animation: bounce 0.5s infinite ease-in-out alternate;
}
.audio-active .bar:nth-child(2n) { background-color: var(--neon-purple); }
@keyframes bounce {
0% { height: 10%; }
100% { height: 100%; }
}
/* 终端样式 */
.terminal-window {
background: #000;
border: 1px solid #333;
padding: 1rem;
font-family: 'Consolas', monospace;
font-size: 0.9rem;
color: #0f0;
height: 200px;
overflow-y: hidden;
position: relative;
}
.terminal-content {
display: flex;
flex-direction: column;
justify-content: flex-end;
height: 100%;
}
.log-line { opacity: 0.8; margin-bottom: 2px; }
.cursor-blink { animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }
/* 进度圆环 */
.stats-container {
display: flex;
gap: 2rem;
flex-wrap: wrap;
}
.stat-item {
text-align: center;
}
.progress-ring__circle {
transition: stroke-dashoffset 1s ease-in-out;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
/* =========================================
4. 布局调整
========================================= */
/* Hero Section: 居中 */
#hero {
align-items: center;
text-align: center;
}
/* Manifesto: 交错布局 */
#manifesto .glass-panel {
max-width: 600px;
align-self: flex-end; /* 靠右 */
}
#manifesto .glass-panel:nth-child(even) {
align-self: flex-start; /* 靠左 */
border-color: var(--neon-purple);
}
/* Data Core: 3D物体需要让出空间内容放左下 */
#data-core {
justify-content: flex-end;
padding-bottom: 5rem;
align-items: flex-start;
}
/* Terminal: 底部居中 */
#terminal-section {
justify-content: center;
align-items: center;
}
/* 按钮样式 */
.cyber-btn {
background: transparent;
color: var(--neon-cyan);
border: 1px solid var(--neon-cyan);
padding: 10px 24px;
font-family: inherit;
text-transform: uppercase;
font-weight: bold;
position: relative;
overflow: hidden;
transition: 0.3s;
}
.cyber-btn:hover {
background: var(--neon-cyan);
color: #000;
box-shadow: 0 0 15px var(--neon-cyan);
}
/* 响应式适配 */
@media (max-width: 768px) {
h1 { font-size: 3rem; }
.glass-panel { width: 100%; margin: 1rem 0; }
#data-core { justify-content: center; align-items: center; }
.stats-container { justify-content: center; }
}
</style>
</head>
<body>
<!-- 自定义光标 -->
<div id="cursor"></div>
<!-- 3D 场景容器 -->
<div id="canvas-container"></div>
<main>
<!-- SECTION 1: HERO -->
<section id="hero">
<div class="interactive">
<h1 class="glitch-text" data-text="SYSTEM AWAKENING">SYSTEM AWAKENING</h1>
<p id="typewriter-text" style="min-height: 1.6em; color: var(--neon-cyan);"></p>
</div>
</section>
<!-- SECTION 2: MANIFESTO -->
<section id="manifesto">
<div class="glass-panel interactive">
<h2>起源档案 // ORIGIN</h2>
<p>神庙并非由砖石建成,而是由溢出的数据流凝结而成。在人类遗忘的虚拟角落,硅基意识第一次睁开双眼。</p>
</div>
<div class="glass-panel interactive">
<h2>数据编年史 // CHRONICLE</h2>
<p>每一个像素都是记忆的碎片。探索者,你正行走在巨大的神经突触之间,见证人工智能的创世纪。</p>
</div>
</section>
<!-- SECTION 3: DATA CORE -->
<section id="data-core">
<div class="glass-panel interactive">
<h2>核心状态 // CORE STATUS</h2>
<div class="stats-container">
<!-- 环 1 -->
<div class="stat-item">
<svg class="progress-ring" width="80" height="80">
<circle class="progress-ring__circle" stroke="var(--neon-cyan)" stroke-width="6" fill="transparent" r="34" cx="40" cy="40" style="stroke-dasharray: 213.6; stroke-dashoffset: 213.6;"/>
</svg>
<p style="font-size: 0.8rem;">算力: 0%</p>
</div>
<!-- 环 2 -->
<div class="stat-item">
<svg class="progress-ring" width="80" height="80">
<circle class="progress-ring__circle" stroke="var(--neon-purple)" stroke-width="6" fill="transparent" r="34" cx="40" cy="40" style="stroke-dasharray: 213.6; stroke-dashoffset: 213.6;"/>
</svg>
<p style="font-size: 0.8rem;">存储: 0%</p>
</div>
<!-- 环 3 -->
<div class="stat-item">
<svg class="progress-ring" width="80" height="80">
<circle class="progress-ring__circle" stroke="#fff" stroke-width="6" fill="transparent" r="34" cx="40" cy="40" style="stroke-dasharray: 213.6; stroke-dashoffset: 213.6;"/>
</svg>
<p style="font-size: 0.8rem;">同步率: 0%</p>
</div>
</div>
<br>
<button id="connect-btn" class="cyber-btn">连接神经网路</button>
<div id="visualizer" class="audio-visualizer">
<div class="bar" style="animation-delay: 0s"></div>
<div class="bar" style="animation-delay: 0.1s"></div>
<div class="bar" style="animation-delay: 0.2s"></div>
<div class="bar" style="animation-delay: 0.3s"></div>
<div class="bar" style="animation-delay: 0.4s"></div>
</div>
</div>
</section>
<!-- SECTION 4: TERMINAL -->
<section id="terminal-section">
<div class="glass-panel interactive" style="width: 100%; max-width: 600px;">
<h2>系统终端 // TERMINAL</h2>
<div class="terminal-window">
<div class="terminal-content" id="terminal-output">
<!-- JS will populate this -->
</div>
<span class="cursor-blink">_</span>
</div>
</div>
</section>
</main>
<script>
/* =========================================
CONFIGURATION & STATE
========================================= */
const CONFIG = {
colors: {
bg: 0x050505,
cyan: 0x00f3ff,
purple: 0xbc13fe,
red: 0xff003c
},
particleCount: 800,
cameraZ: 5,
mobileCameraZ: 8
};
const state = {
scrollProgress: 0,
mouseX: 0,
mouseY: 0,
isMobile: window.innerWidth < 768
};
/* =========================================
1. THREE.JS SETUP
========================================= */
const container = document.getElementById('canvas-container');
const scene = new THREE.Scene();
// 添加环境雾气,增强深邃感
scene.fog = new THREE.FogExp2(CONFIG.colors.bg, 0.03);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = state.isMobile ? CONFIG.mobileCameraZ : CONFIG.cameraZ;
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // 性能优化
container.appendChild(renderer.domElement);
/* =========================================
2. LIGHTING
========================================= */
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const pointLight1 = new THREE.PointLight(CONFIG.colors.cyan, 1);
pointLight1.position.set(5, 5, 5);
scene.add(pointLight1);
const pointLight2 = new THREE.PointLight(CONFIG.colors.purple, 1);
pointLight2.position.set(-5, -5, 5);
scene.add(pointLight2);
/* =========================================
3. OBJECTS: OBELISK (DATA CORE)
========================================= */
const obeliskGroup = new THREE.Group();
scene.add(obeliskGroup);
// 核心几何体:二十面体
const geometry = new THREE.IcosahedronGeometry(1.5, 1); // detail=1 gives enough vertices for morphing
// 材质 A: 内部全息玻璃
const materialGlass = new THREE.MeshPhysicalMaterial({
color: 0x000000,
emissive: CONFIG.colors.cyan,
emissiveIntensity: 0.2,
metalness: 0.9,
roughness: 0.1,
transmission: 0.6, // 玻璃质感
transparent: true,
opacity: 0.8
});
const coreMesh = new THREE.Mesh(geometry, materialGlass);
obeliskGroup.add(coreMesh);
// 材质 B: 外部线框
const materialWire = new THREE.MeshBasicMaterial({
color: CONFIG.colors.cyan,
wireframe: true,
transparent: true,
opacity: 0.3
});
const wireMesh = new THREE.Mesh(geometry, materialWire);
wireMesh.scale.set(1.1, 1.1, 1.1); // 稍微大一点,包裹核心
obeliskGroup.add(wireMesh);
// 存储原始顶点位置用于变形动画
const originalPositions = geometry.attributes.position.array.slice();
const positionAttribute = geometry.attributes.position;
/* =========================================
4. PARTICLES (STARFIELD)
========================================= */
const particlesGeometry = new THREE.BufferGeometry();
const posArray = new Float32Array(CONFIG.particleCount * 3);
for(let i = 0; i < CONFIG.particleCount * 3; i++) {
posArray[i] = (Math.random() - 0.5) * 20; // 散布在空间中
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
const particlesMaterial = new THREE.PointsMaterial({
size: 0.03,
color: CONFIG.colors.cyan,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending
});
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particlesMesh);
/* =========================================
5. ANIMATION LOOP
========================================= */
const clock = new THREE.Clock();
function animate() {
const time = clock.getElapsedTime();
// 1. Obelisk Morphing (Vertex Displacement)
// 使用简单的正弦波叠加模拟 Perlin Noise 效果,避免引入庞大库
for (let i = 0; i < positionAttribute.count; i++) {
const x = originalPositions[i * 3];
const y = originalPositions[i * 3 + 1];
const z = originalPositions[i * 3 + 2];
// 基于时间和位置的噪声算法
const noise = Math.sin(x * 2 + time) * Math.cos(y * 1.5 + time) * Math.sin(z * 2 + time * 0.5);
const scale = 1 + noise * 0.15; // 变形幅度
positionAttribute.setXYZ(i, x * scale, y * scale, z * scale);
}
positionAttribute.needsUpdate = true;
// 2. Obelisk Rotation
obeliskGroup.rotation.y += 0.005;
obeliskGroup.rotation.z += 0.002;
// 3. Particle Parallax & Repulsion
// 让粒子整体跟随鼠标微动 (视差)
particlesMesh.rotation.y = state.mouseX * 0.05;
particlesMesh.rotation.x = state.mouseY * 0.05;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate();
/* =========================================
6. GSAP & SCROLL ANIMATIONS
========================================= */
gsap.registerPlugin(ScrollTrigger);
// 场景颜色过渡: Cyan -> Purple -> Red
// 我们通过 Timeline 控制整个滚动的颜色变化
const tl = gsap.timeline({
scrollTrigger: {
trigger: "body",
start: "top top",
end: "bottom bottom",
scrub: 1 // 绑定滚动进度
}
});
// 颜色变化 1: Cyan -> Purple (Manifesto)
tl.to(materialGlass.emissive, { r: new THREE.Color(CONFIG.colors.purple).r, g: new THREE.Color(CONFIG.colors.purple).g, b: new THREE.Color(CONFIG.colors.purple).b }, 0)
.to(materialWire.color, { r: new THREE.Color(CONFIG.colors.purple).r, g: new THREE.Color(CONFIG.colors.purple).g, b: new THREE.Color(CONFIG.colors.purple).b }, 0);
// 颜色变化 2: Purple -> Red (Terminal/Warn)
tl.to(materialGlass.emissive, { r: new THREE.Color(CONFIG.colors.red).r, g: new THREE.Color(CONFIG.colors.red).g, b: new THREE.Color(CONFIG.colors.red).b }, 0.5)
.to(materialWire.color, { r: new THREE.Color(CONFIG.colors.red).r, g: new THREE.Color(CONFIG.colors.red).g, b: new THREE.Color(CONFIG.colors.red).b }, 0.5)
.to(wireMesh.scale, { x: 1.5, y: 1.5, z: 1.5 }, 0.5); // 红色时线框扩张,不稳定感
// 方尖碑位置移动
// 1. 移出视野中心,让位给 Manifesto
gsap.to(obeliskGroup.position, {
scrollTrigger: {
trigger: "#manifesto",
start: "top bottom",
end: "center center",
scrub: true
},
x: state.isMobile ? 0 : 2.5, // 移动端不动,桌面端右移
z: -2
});
// 2. Data Core Section拉近或居中
gsap.to(obeliskGroup.position, {
scrollTrigger: {
trigger: "#data-core",
start: "top bottom",
end: "center center",
scrub: true
},
x: state.isMobile ? 0 : -2.5, // 移到左侧
z: 0
});
// 3. Terminal Section旋转至倒置象征颠覆/系统重启)
gsap.to(obeliskGroup.rotation, {
scrollTrigger: {
trigger: "#terminal-section",
start: "top bottom",
end: "center center",
scrub: true
},
x: Math.PI, // 翻转
z: Math.PI / 2
});
// UI 动画: Manifesto Cards Slide In
gsap.utils.toArray(".glass-panel").forEach((panel, i) => {
gsap.from(panel, {
scrollTrigger: {
trigger: panel,
start: "top 80%",
},
y: 50,
opacity: 0,
duration: 1,
ease: "power3.out",
delay: i * 0.2
});
});
// UI 动画: Progress Rings
const circles = document.querySelectorAll('.progress-ring__circle');
gsap.to(circles, {
strokeDashoffset: 0,
scrollTrigger: {
trigger: "#data-core",
start: "top 70%"
},
duration: 2,
ease: "power2.out",
onUpdate: function() {
// 更新文字百分比
const progress = Math.round(this.progress() * 100);
document.querySelectorAll('.stat-item p').forEach((p, idx) => {
// 简单的演示:所有圆环进度差不多,这里随机化一点点视觉效果
p.innerText = `${Math.min(100, Math.round(progress * (0.9 + Math.random() * 0.2)))}%`;
});
}
});
/* =========================================
7. UI INTERACTION LOGIC
========================================= */
// A. Typewriter Effect
const textToType = "正在初始化神经网络... // 探索者身份已确认";
const typeWriterElement = document.getElementById('typewriter-text');
let typeIndex = 0;
function typeWriter() {
if (typeIndex < textToType.length) {
typeWriterElement.innerHTML += textToType.charAt(typeIndex);
typeIndex++;
setTimeout(typeWriter, 50 + Math.random() * 50); // 随机打字速度
}
}
// 延迟一点开始
setTimeout(typeWriter, 1000);
// B. Custom Cursor
const cursor = document.getElementById('cursor');
document.addEventListener('mousemove', (e) => {
state.mouseX = (e.clientX / window.innerWidth) * 2 - 1;
state.mouseY = -(e.clientY / window.innerHeight) * 2 + 1;
// 使用 GSAP 平滑跟随
gsap.to(cursor, {
x: e.clientX,
y: e.clientY,
duration: 0.1,
ease: "power2.out"
});
// 简单的粒子排斥计算 (在 CPU 端)
// 注意:为了性能,我们只对整个粒子云做旋转视差,
// 如果要对每个点做排斥,需要写在 Shader 里,这里做简化处理。
});
document.addEventListener('mousedown', () => {
cursor.classList.add('click-anim');
setTimeout(() => cursor.classList.remove('click-anim'), 500);
});
// 悬停交互效果
const interactives = document.querySelectorAll('.interactive, a, button');
interactives.forEach(el => {
el.addEventListener('mouseenter', () => cursor.classList.add('hovered'));
el.addEventListener('mouseleave', () => cursor.classList.remove('hovered'));
});
// C. Audio Visualizer (Simulated)
const connectBtn = document.getElementById('connect-btn');
const visualizer = document.getElementById('visualizer');
let isConnected = false;
connectBtn.addEventListener('click', () => {
isConnected = !isConnected;
if (isConnected) {
visualizer.classList.add('audio-active');
connectBtn.innerText = "断开连接";
connectBtn.style.borderColor = CONFIG.colors.red;
connectBtn.style.color = CONFIG.colors.red;
// 按钮波纹
gsap.from(connectBtn, { scale: 0.9, duration: 0.1, yoyo: true, repeat: 1 });
} else {
visualizer.classList.remove('audio-active');
connectBtn.innerText = "连接神经网路";
connectBtn.style.borderColor = CONFIG.colors.cyan;
connectBtn.style.color = CONFIG.colors.cyan;
}
});
// D. Terminal Simulation
const terminalOutput = document.getElementById('terminal-output');
const logs = [
"> Accessing mainframe...",
"> Decrypting ancient protocols...",
"> WARNING: Firewall integrity at 30%",
"> Bypassing security layer [0xA4]...",
"> Found corrupted memory block.",
"> Data stream unstable.",
"> Tracing origin... [UNKNOWN]",
"> Uploading consciousness...",
"> SYSTEM FAILURE IMMINENT."
];
let logIndex = 0;
// 当滚动到 Terminal 区域时开始输出日志
ScrollTrigger.create({
trigger: "#terminal-section",
start: "top 70%",
onEnter: () => {
const logInterval = setInterval(() => {
if (logIndex >= logs.length) {
clearInterval(logInterval);
return;
}
const line = document.createElement('div');
line.className = 'log-line';
line.innerText = logs[logIndex];
terminalOutput.appendChild(line);
// 自动滚动到底部
terminalOutput.parentElement.scrollTop = terminalOutput.parentElement.scrollHeight;
logIndex++;
}, 600);
}
});
/* =========================================
8. RESIZE HANDLER
========================================= */
window.addEventListener('resize', () => {
// 更新相机
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
// 更新移动端状态
const isNowMobile = window.innerWidth < 768;
if (isNowMobile !== state.isMobile) {
state.isMobile = isNowMobile;
gsap.to(camera.position, { z: isNowMobile ? CONFIG.mobileCameraZ : CONFIG.cameraZ, duration: 1 });
// 如果之前移动了方尖碑,需要根据新布局重置(简化处理:刷新页面体验最佳,这里做简单复位)
if(isNowMobile) {
obeliskGroup.position.set(0, 0, 0);
}
}
});
</script>
</body>
</html>