Files
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

561 lines
21 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>八卦阵 - 太极玄奥秘术</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #0a0a0f;
font-family: 'Microsoft YaHei', sans-serif;
}
#canvas-container {
width: 100vw;
height: 100vh;
}
#info {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
color: #ffd700;
text-align: center;
font-size: 14px;
text-shadow: 0 0 10px #ffd700, 0 0 20px #ffd700;
pointer-events: none;
z-index: 100;
letter-spacing: 3px;
}
#mode {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: #00ffff;
font-size: 12px;
text-shadow: 0 0 5px #00ffff;
pointer-events: none;
letter-spacing: 2px;
}
.glow-text {
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.8; }
50% { opacity: 1; }
}
</style>
</head>
<body>
<div id="info">
<div class="glow-text">☯ 八卦阵 · 太极玄奥秘术 ☯</div>
<div style="font-size: 12px; margin-top: 8px; color: #9d4edd;">点击切换阵法 · 乾坎艮震巽离坤兑</div>
</div>
<div id="mode">当前阵法:顺时针旋转</div>
<div id="canvas-container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// 场景设置
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x0a0a1a, 0.02);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 25);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.getElementById('canvas-container').appendChild(renderer.domElement);
// 颜色定义
const COLORS = {
gold: 0xffd700,
cyan: 0x00ffff,
purple: 0x9d4edd,
darkPurple: 0x1a0a2e,
white: 0xffffff,
black: 0x000000
};
// 创建发光材质
function createGlowMaterial(color, opacity = 1) {
return new THREE.LineBasicMaterial({
color: color,
transparent: true,
opacity: opacity,
blending: THREE.AdditiveBlending,
side: THREE.DoubleSide
});
}
// 创建点发光效果
function createPointGlow(color, size = 0.3) {
const geometry = new THREE.SphereGeometry(size, 16, 16);
const material = new THREE.MeshBasicMaterial({
color: color,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending
});
return new THREE.Mesh(geometry, material);
}
// ===== 太极图 =====
const taijiGroup = new THREE.Group();
// 外圆
const outerCircleGeometry = new THREE.RingGeometry(3.8, 4, 64);
const outerCircleMaterial = new THREE.MeshBasicMaterial({
color: COLORS.gold,
transparent: true,
opacity: 0.6,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending
});
const outerCircle = new THREE.Mesh(outerCircleGeometry, outerCircleMaterial);
outerCircle.rotation.x = Math.PI / 2;
taijiGroup.add(outerCircle);
// 太极S曲线
const sCurvePoints = [];
for (let i = 0; i <= 100; i++) {
const t = i / 100;
const angle = t * Math.PI * 2;
const r = 2 + Math.cos(angle) * 2;
const x = Math.cos(angle) * r * 0.5;
const y = Math.sin(angle) * r;
sCurvePoints.push(new THREE.Vector3(x, y, 0));
}
const sCurveGeometry = new THREE.BufferGeometry().setFromPoints(sCurvePoints);
const sCurveMaterial = createGlowMaterial(COLORS.white, 0.9);
const sCurve = new THREE.Line(sCurveGeometry, sCurveMaterial);
taijiGroup.add(sCurve);
// 阴阳鱼眼
const yinEye = createPointGlow(COLORS.white, 0.4);
yinEye.position.set(0, 1, 0.1);
taijiGroup.add(yinEye);
const yangEye = createPointGlow(COLORS.black, 0.4);
yangEye.position.set(0, -1, 0.1);
taijiGroup.add(yangEye);
// 阴阳半圆(简化版)
const yinGeometry = new THREE.CircleGeometry(4, 64, Math.PI / 2, Math.PI);
const yinMaterial = new THREE.MeshBasicMaterial({
color: COLORS.black,
transparent: true,
opacity: 0.7,
side: THREE.DoubleSide
});
const yinCircle = new THREE.Mesh(yinGeometry, yinMaterial);
taijiGroup.add(yinCircle);
const yangGeometry = new THREE.CircleGeometry(4, 64, -Math.PI / 2, Math.PI);
const yangMaterial = new THREE.MeshBasicMaterial({
color: COLORS.white,
transparent: true,
opacity: 0.7,
side: THREE.DoubleSide
});
const yangCircle = new THREE.Mesh(yangGeometry, yangMaterial);
taijiGroup.add(yangCircle);
// 内圈装饰
const innerRingGeometry = new THREE.RingGeometry(3.5, 3.6, 64);
const innerRingMaterial = new THREE.MeshBasicMaterial({
color: COLORS.cyan,
transparent: true,
opacity: 0.4,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending
});
const innerRing = new THREE.Mesh(innerRingGeometry, innerRingMaterial);
innerRing.rotation.x = Math.PI / 2;
taijiGroup.add(innerRing);
scene.add(taijiGroup);
// ===== 八卦符号 =====
const baguaGroup = new THREE.Group();
const guaGroups = [];
// 八卦数据:名称、符号(三爻)、角度位置
const baguaData = [
{ name: '乾', symbol: [1, 1, 1], angle: 0, color: COLORS.gold },
{ name: '兑', symbol: [0, 1, 1], angle: Math.PI / 4, color: COLORS.cyan },
{ name: '离', symbol: [1, 0, 1], angle: Math.PI / 2, color: COLORS.gold },
{ name: '震', symbol: [0, 0, 1], angle: Math.PI * 3 / 4, color: COLORS.cyan },
{ name: '巽', symbol: [1, 1, 0], angle: Math.PI, color: COLORS.purple },
{ name: '坎', symbol: [0, 1, 0], angle: Math.PI * 5 / 4, color: COLORS.cyan },
{ name: '艮', symbol: [1, 0, 0], angle: Math.PI * 3 / 2, color: COLORS.purple },
{ name: '坤', symbol: [0, 0, 0], angle: Math.PI * 7 / 4, color: COLORS.gold }
];
// 创建单个卦象符号
function createGuaSymbol(gua, radius) {
const group = new THREE.Group();
// 三爻
const yaoHeight = 0.8;
const yaoWidth = 1.2;
const yaoGap = 0.3;
gua.symbol.forEach((yao, index) => {
const y = (1 - index) * (yaoHeight + yaoGap);
if (yao === 1) {
// 阳爻 — 实线
const points = [
new THREE.Vector3(-yaoWidth / 2, y, 0),
new THREE.Vector3(yaoWidth / 2, y, 0)
];
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = createGlowMaterial(gua.color, 0.9);
const line = new THREE.Line(geometry, material);
line.userData = { isYang: true };
group.add(line);
// 发光增强
const glowPoints = [
new THREE.Vector3(-yaoWidth / 2 - 0.05, y, 0),
new THREE.Vector3(yaoWidth / 2 + 0.05, y, 0)
];
const glowGeometry = new THREE.BufferGeometry().setFromPoints(glowPoints);
const glowMaterial = createGlowMaterial(gua.color, 0.3);
const glowLine = new THREE.Line(glowGeometry, glowMaterial);
glowLine.scale.set(1.2, 1.2, 1.2);
group.add(glowLine);
} else {
// 阴爻 - - 断线
const segmentWidth = yaoWidth * 0.4;
const gap = yaoWidth * 0.2;
// 左段
const leftPoints = [
new THREE.Vector3(-yaoWidth / 2, y, 0),
new THREE.Vector3(-yaoWidth / 2 + segmentWidth, y, 0)
];
const leftGeometry = new THREE.BufferGeometry().setFromPoints(leftPoints);
const leftMaterial = createGlowMaterial(gua.color, 0.9);
group.add(new THREE.Line(leftGeometry, leftMaterial));
// 右段
const rightPoints = [
new THREE.Vector3(yaoWidth / 2 - segmentWidth, y, 0),
new THREE.Vector3(yaoWidth / 2, y, 0)
];
const rightGeometry = new THREE.BufferGeometry().setFromPoints(rightPoints);
group.add(new THREE.Line(rightGeometry, leftMaterial));
}
});
// 卦象外框
const frameSize = 1.5;
const framePoints = [
new THREE.Vector3(-frameSize, -frameSize * 1.2, 0),
new THREE.Vector3(frameSize, -frameSize * 1.2, 0),
new THREE.Vector3(frameSize, frameSize * 1.2, 0),
new THREE.Vector3(-frameSize, frameSize * 1.2, 0),
new THREE.Vector3(-frameSize, -frameSize * 1.2, 0)
];
const frameGeometry = new THREE.BufferGeometry().setFromPoints(framePoints);
const frameMaterial = createGlowMaterial(gua.color, 0.4);
const frame = new THREE.Line(frameGeometry, frameMaterial);
group.add(frame);
// 卦名标记点
const nameDot = createPointGlow(gua.color, 0.15);
nameDot.position.set(0, frameSize * 1.4, 0);
group.add(nameDot);
// 设置位置
const x = Math.cos(gua.angle) * radius;
const z = Math.sin(gua.angle) * radius;
group.position.set(x, 0, z);
// 让卦象面向中心
group.lookAt(0, 0, 0);
group.rotateY(Math.PI);
group.userData = {
gua: gua,
originalAngle: gua.angle,
radius: radius,
rotationSpeed: (Math.random() - 0.5) * 0.02
};
return group;
}
// 创建所有八卦
const mainRadius = 10;
baguaData.forEach(gua => {
const guaGroup = createGuaSymbol(gua, mainRadius);
guaGroups.push(guaGroup);
baguaGroup.add(guaGroup);
});
scene.add(baguaGroup);
// ===== 能量连接线 =====
const energyLinesGroup = new THREE.Group();
const energyLines = [];
function createEnergyLine(start, end, color) {
const points = [start, end];
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = createGlowMaterial(color, 0.3);
const line = new THREE.Line(geometry, material);
return line;
}
// 相邻卦象间的连接线
for (let i = 0; i < guaGroups.length; i++) {
const current = guaGroups[i];
const next = guaGroups[(i + 1) % guaGroups.length];
const line = createEnergyLine(
current.position.clone(),
next.position.clone(),
COLORS.purple
);
energyLines.push({
line: line,
startIndex: i,
endIndex: (i + 1) % guaGroups.length
});
energyLinesGroup.add(line);
}
// 对角线连接(五行相生)
const diagonalPairs = [[0, 4], [1, 5], [2, 6], [3, 7]];
diagonalPairs.forEach(([a, b]) => {
const line = createEnergyLine(
guaGroups[a].position.clone(),
guaGroups[b].position.clone(),
COLORS.cyan
);
line.material.opacity = 0.15;
energyLines.push({
line: line,
startIndex: a,
endIndex: b
});
energyLinesGroup.add(line);
});
// 中心到各卦象的能量线
guaGroups.forEach((gua, index) => {
const centerPoint = new THREE.Vector3(0, 0, 0);
const guaPoint = gua.position.clone().multiplyScalar(0.4);
const points = [];
const segments = 20;
for (let i = 0; i <= segments; i++) {
const t = i / segments;
const point = centerPoint.clone().lerp(guaPoint, t);
// 添加一些波动
point.y += Math.sin(t * Math.PI * 3) * 0.3;
points.push(point);
}
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = createGlowMaterial(gua.userData.gua.color, 0.25);
const line = new THREE.Line(geometry, material);
energyLinesGroup.add(line);
});
scene.add(energyLinesGroup);
// ===== 外围装饰环 =====
const outerRingGroup = new THREE.Group();
// 主外环
const mainRingGeometry = new THREE.RingGeometry(mainRadius - 0.5, mainRadius + 0.5, 64);
const mainRingMaterial = new THREE.MeshBasicMaterial({
color: COLORS.purple,
transparent: true,
opacity: 0.2,
side: THREE.DoubleSide,
blending: THREE.AdditiveBlending
});
const mainRing = new THREE.Mesh(mainRingGeometry, mainRingMaterial);
mainRing.rotation.x = Math.PI / 2;
outerRingGroup.add(mainRing);
// 装饰符文点
for (let i = 0; i < 24; i++) {
const angle = (i / 24) * Math.PI * 2;
const x = Math.cos(angle) * (mainRadius + 1.5);
const z = Math.sin(angle) * (mainRadius + 1.5);
const dot = createPointGlow(i % 2 === 0 ? COLORS.gold : COLORS.cyan, 0.08);
dot.position.set(x, 0, z);
outerRingGroup.add(dot);
}
// 内圈旋转环
const innerRotateRingGeometry = new THREE.RingGeometry(5.5, 5.7, 64);
const innerRotateRing = new THREE.Mesh(innerRotateRingGeometry, mainRingMaterial.clone());
innerRotateRing.material.color.setHex(COLORS.cyan);
innerRotateRing.material.opacity = 0.3;
innerRotateRing.rotation.x = Math.PI / 2;
outerRingGroup.add(innerRotateRing);
scene.add(outerRingGroup);
// ===== 粒子效果 =====
const particlesGeometry = new THREE.BufferGeometry();
const particlesCount = 200;
const posArray = new Float32Array(particlesCount * 3);
for (let i = 0; i < particlesCount * 3; i += 3) {
const angle = Math.random() * Math.PI * 2;
const radius = 6 + Math.random() * 8;
posArray[i] = Math.cos(angle) * radius;
posArray[i + 1] = (Math.random() - 0.5) * 4;
posArray[i + 2] = Math.sin(angle) * radius;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
const particlesMaterial = new THREE.PointsMaterial({
size: 0.05,
color: COLORS.gold,
transparent: true,
opacity: 0.6,
blending: THREE.AdditiveBlending
});
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles);
// ===== 动画状态 =====
let mode = 0; // 0: 顺时针, 1: 逆时针, 2: 内外翻转
const modes = ['顺时针旋转', '逆时针旋转', '内外翻转'];
// 点击切换
document.addEventListener('click', () => {
mode = (mode + 1) % 3;
document.getElementById('mode').textContent = `当前阵法:${modes[mode]}`;
});
// 鼠标移动视差效果
let mouseX = 0, mouseY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = (e.clientX / window.innerWidth - 0.5) * 2;
mouseY = (e.clientY / window.innerHeight - 0.5) * 2;
});
// 动画循环
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const time = clock.getElapsedTime();
const delta = clock.getDelta();
// 太极图旋转
taijiGroup.rotation.y = time * 0.1;
taijiGroup.rotation.z = Math.sin(time * 0.5) * 0.05;
// 内圈环反向旋转
innerRotateRing.rotation.z = -time * 0.3;
// 八卦整体旋转(根据模式)
let rotationSpeed = 0.05;
if (mode === 1) rotationSpeed = -0.05;
baguaGroup.rotation.y += rotationSpeed * 0.02;
outerRingGroup.rotation.y += rotationSpeed * 0.01;
// 各卦象自转
guaGroups.forEach((gua, index) => {
const offset = index * (Math.PI / 4);
if (mode === 2) {
// 内外翻转模式
const flipRadius = mainRadius + Math.sin(time * 0.5 + offset) * 3;
const angle = gua.userData.originalAngle + baguaGroup.rotation.y;
gua.position.x = Math.cos(angle) * flipRadius;
gua.position.z = Math.sin(angle) * flipRadius;
gua.lookAt(0, 0, 0);
gua.rotateY(Math.PI);
}
// 自转
gua.children.forEach(child => {
if (child.userData.isYang) {
child.rotation.z = time * 0.2;
}
});
});
// 更新能量线
energyLines.forEach(conn => {
const start = guaGroups[conn.startIndex].position.clone();
const end = guaGroups[conn.endIndex].position.clone();
conn.line.geometry.setFromPoints([start, end]);
});
// 粒子动画
particles.rotation.y = time * 0.02;
const positions = particles.geometry.attributes.position.array;
for (let i = 1; i < positions.length; i += 3) {
positions[i] += Math.sin(time + positions[i - 1]) * 0.002;
}
particles.geometry.attributes.position.needsUpdate = true;
// 视差效果
camera.position.x += (mouseX * 2 - camera.position.x) * 0.02;
camera.position.y += (-mouseY * 2 - camera.position.y) * 0.02;
camera.lookAt(0, 0, 0);
// 颜色脉动
outerCircle.material.opacity = 0.4 + Math.sin(time * 2) * 0.2;
mainRing.material.opacity = 0.15 + Math.sin(time * 1.5) * 0.1;
renderer.render(scene, camera);
}
animate();
// 窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// 添加星空背景效果
const starsGeometry = new THREE.BufferGeometry();
const starsCount = 1000;
const starsPos = new Float32Array(starsCount * 3);
for (let i = 0; i < starsCount * 3; i++) {
starsPos[i] = (Math.random() - 0.5) * 200;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(starsPos, 3));
const starsMaterial = new THREE.PointsMaterial({
size: 0.1,
color: 0xffffff,
transparent: true,
opacity: 0.5
});
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
</script>
</body>
</html>