generated from dellevin/template
优化星云相册
This commit is contained in:
@@ -3,7 +3,21 @@
|
||||
"allow": [
|
||||
"mcp__Claude_Preview__preview_start",
|
||||
"WebFetch(domain:cdnjs.cloudflare.com)",
|
||||
"Bash(curl -L -o \"D:\\\\UserData\\\\Desktop\\\\my_proj\\\\www.iletter.top\\\\static\\\\js\\\\three.min.js\" \"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\")"
|
||||
"Bash(curl -L -o \"D:\\\\UserData\\\\Desktop\\\\my_proj\\\\www.iletter.top\\\\static\\\\js\\\\three.min.js\" \"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\")",
|
||||
"Bash(curl -L -o sun.jpg \"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/The_Sun_by_the_Atmospheric_Imaging_Assembly_of_NASA%27s_Solar_Dynamics_Observatory_-_20100819.jpg/1200px-The_Sun_by_the_Atmospheric_Imaging_Assembly_of_NASA%27s_Solar_Dynamics_Observatory_-_20100819.jpg\")",
|
||||
"Bash(curl -L -o earth.jpg \"https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/The_Blue_Marble_%28remastered%29.jpg/1200px-The_Blue_Marble_%28remastered%29.jpg\")",
|
||||
"Bash(curl -L -o mars.jpg \"https://upload.wikimedia.org/wikipedia/commons/thumb/0/0c/Mars_-_August_30_2021_-_Flipped.jpg/1200px-Mars_-_August_30_2021_-_Flipped.jpg\")",
|
||||
"Bash(curl -L -o saturn.jpg \"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Saturn_during_Equinox.jpg/1200px-Saturn_during_Equinox.jpg\")",
|
||||
"Bash(curl -L -o jupiter.jpg \"https://upload.wikimedia.org/wikipedia/commons/thumb/c/c1/Jupiter_New_Horizons.jpg/1200px-Jupiter_New_Horizons.jpg\")",
|
||||
"Bash(curl -sL \"https://upload.wikimedia.org/wikipedia/commons/thumb/b/b4/The_Sun_by_the_Atmospheric_Imaging_Assembly_of_NASA%27s_Solar_Dynamics_Observatory_-_20100819.jpg/600px-The_Sun_by_the_Atmospheric_Imaging_Assembly_of_NASA%27s_Solar_Dynamics_Observatory_-_20100819.jpg\" -o sun.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1506318137071-a8e063b4bec0?w=300\" -o sun.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1614730321146-b6fa6a46bcb4?w=300\" -o earth.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1614728894747-a83421e2b9c9?w=300\" -o mars.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1614732414444-096e5f1122d5?w=300\" -o saturn.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1614313913007-2b4ae8ce32d6?w=300\" -o jupiter.jpg)",
|
||||
"Bash(curl -sL \"https://images.unsplash.com/photo-1446776811953-b23d57bd21aa?w=2048&q=80\" -o moon.jpg)",
|
||||
"Bash(curl -sL \"https://svs.gsfc.nasa.gov/vis/a000000/a004700/a004720/lroc_color_poles_4096.jpg\" -o moon.jpg)",
|
||||
"Bash(curl -sL \"https://upload.wikimedia.org/wikipedia/commons/thumb/d/db/Moonmap_from_clementine_data.png/1280px-Moonmap_from_clementine_data.png\" -o moon.png)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,102 +161,15 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
/* 第一大区域 - 各种随机位置和大小 */
|
||||
radial-gradient(1px 1px at 5px 15px, #fff, transparent),
|
||||
radial-gradient(2px 2px at 45px 8px, rgba(255,255,255,0.85), transparent),
|
||||
radial-gradient(1px 1px at 82px 42px, rgba(255,255,255,0.6), transparent),
|
||||
radial-gradient(3px 3px at 120px 25px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 155px 58px, rgba(255,255,255,0.9), transparent),
|
||||
radial-gradient(2px 2px at 192px 12px, rgba(255,255,255,0.4), transparent),
|
||||
radial-gradient(1px 1px at 228px 48px, #fff, transparent),
|
||||
radial-gradient(2px 2px at 265px 32px, rgba(255,255,255,0.7), transparent),
|
||||
radial-gradient(1px 1px at 302px 65px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 338px 8px, #fff, transparent),
|
||||
radial-gradient(2px 2px at 375px 42px, rgba(255,255,255,0.8), transparent),
|
||||
radial-gradient(1px 1px at 412px 18px, rgba(255,255,255,0.6), transparent),
|
||||
radial-gradient(2px 2px at 448px 55px, rgba(255,255,255,0.3), transparent),
|
||||
radial-gradient(1px 1px at 485px 38px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 522px 72px, rgba(255,255,255,0.7), transparent),
|
||||
radial-gradient(3px 3px at 558px 28px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 595px 52px, #fff, transparent),
|
||||
/* 第二大区域 - 更随机的分布 */
|
||||
radial-gradient(2px 2px at 22px 78px, rgba(255,255,255,0.45), transparent),
|
||||
radial-gradient(1px 1px at 68px 92px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 108px 85px, rgba(255,255,255,0.55), transparent),
|
||||
radial-gradient(2px 2px at 145px 98px, rgba(255,255,255,0.35), transparent),
|
||||
radial-gradient(1px 1px at 182px 88px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 218px 75px, rgba(255,255,255,0.65), transparent),
|
||||
radial-gradient(2px 2px at 255px 95px, rgba(255,255,255,0.45), transparent),
|
||||
radial-gradient(1px 1px at 292px 82px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 328px 98px, rgba(255,255,255,0.75), transparent),
|
||||
radial-gradient(2px 2px at 365px 78px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 402px 92px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 438px 85px, rgba(255,255,255,0.4), transparent),
|
||||
radial-gradient(2px 2px at 475px 95px, rgba(255,255,255,0.6), transparent),
|
||||
radial-gradient(1px 1px at 512px 78px, #fff, transparent),
|
||||
radial-gradient(1px 1px at 548px 88px, rgba(255,255,255,0.8), transparent),
|
||||
radial-gradient(1px 1px at 585px 82px, rgba(255,255,255,0.3), transparent),
|
||||
/* 第三大区域 - 散落的小星星 */
|
||||
radial-gradient(1px 1px at 15px 108px, rgba(255,255,255,0.25), transparent),
|
||||
radial-gradient(1px 1px at 52px 118px, rgba(255,255,255,0.15), transparent),
|
||||
radial-gradient(1px 1px at 88px 112px, rgba(255,255,255,0.35), transparent),
|
||||
radial-gradient(1px 1px at 125px 105px, rgba(255,255,255,0.2), transparent),
|
||||
radial-gradient(1px 1px at 162px 120px, rgba(255,255,255,0.4), transparent),
|
||||
radial-gradient(1px 1px at 198px 108px, rgba(255,255,255,0.3), transparent),
|
||||
radial-gradient(1px 1px at 235px 115px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 272px 102px, rgba(255,255,255,0.2), transparent),
|
||||
radial-gradient(1px 1px at 308px 120px, rgba(255,255,255,0.35), transparent),
|
||||
radial-gradient(1px 1px at 345px 108px, rgba(255,255,255,0.45), transparent),
|
||||
radial-gradient(1px 1px at 382px 115px, rgba(255,255,255,0.15), transparent),
|
||||
radial-gradient(1px 1px at 418px 102px, rgba(255,255,255,0.25), transparent),
|
||||
radial-gradient(1px 1px at 455px 112px, rgba(255,255,255,0.4), transparent),
|
||||
radial-gradient(1px 1px at 492px 105px, rgba(255,255,255,0.3), transparent),
|
||||
radial-gradient(1px 1px at 528px 118px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 565px 108px, rgba(255,255,255,0.2), transparent),
|
||||
radial-gradient(1px 1px at 602px 115px, rgba(255,255,255,0.35), transparent),
|
||||
/* 额外的亮点 */
|
||||
radial-gradient(2px 2px at 35px 55px, rgba(255,255,255,0.6), transparent),
|
||||
radial-gradient(3px 3px at 175px 35px, rgba(255,255,255,0.8), transparent),
|
||||
radial-gradient(2px 2px at 315px 68px, rgba(255,255,255,0.7), transparent),
|
||||
radial-gradient(2px 2px at 455px 25px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 535px 42px, rgba(255,255,255,0.9), transparent),
|
||||
radial-gradient(2px 2px at 75px 68px, rgba(255,255,255,0.65), transparent),
|
||||
radial-gradient(1px 1px at 205px 82px, rgba(255,255,255,0.75), transparent),
|
||||
radial-gradient(3px 3px at 385px 48px, rgba(255,255,255,0.55), transparent),
|
||||
radial-gradient(1px 1px at 505px 72px, rgba(255,255,255,0.85), transparent),
|
||||
radial-gradient(2px 2px at 625px 15px, rgba(255,255,255,0.4), transparent),
|
||||
radial-gradient(1px 1px at 652px 58px, rgba(255,255,255,0.7), transparent),
|
||||
radial-gradient(2px 2px at 688px 32px, rgba(255,255,255,0.6), transparent),
|
||||
radial-gradient(1px 1px at 725px 45px, rgba(255,255,255,0.8), transparent),
|
||||
radial-gradient(2px 2px at 762px 62px, rgba(255,255,255,0.5), transparent),
|
||||
radial-gradient(1px 1px at 798px 18px, rgba(255,255,255,0.65), transparent),
|
||||
radial-gradient(1px 1px at 835px 75px, rgba(255,255,255,0.45), transparent),
|
||||
radial-gradient(2px 2px at 872px 42px, rgba(255,255,255,0.7), transparent),
|
||||
radial-gradient(1px 1px at 908px 28px, rgba(255,255,255,0.55), transparent),
|
||||
radial-gradient(2px 2px at 945px 65px, rgba(255,255,255,0.8), transparent),
|
||||
radial-gradient(1px 1px at 982px 38px, rgba(255,255,255,0.4), transparent);
|
||||
background-repeat: repeat;
|
||||
background-size: 1000px 130px;
|
||||
animation: twinkle 3s ease-in-out infinite alternate, drift 20s linear infinite;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image: url('../img/planets/bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0% { opacity: 0.4; }
|
||||
33% { opacity: 0.7; }
|
||||
66% { opacity: 0.5; }
|
||||
100% { opacity: 0.8; }
|
||||
}
|
||||
|
||||
@keyframes drift {
|
||||
0% { transform: translate(0, 0); }
|
||||
100% { transform: translate(-10px, -5px); }
|
||||
}
|
||||
|
||||
.galaxy-canvas-wrapper canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
BIN
static/img/planets/bg.jpg
Normal file
BIN
static/img/planets/bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 409 KiB |
BIN
static/img/planets/earth.jpg
Normal file
BIN
static/img/planets/earth.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
static/img/planets/moon.jpg
Normal file
BIN
static/img/planets/moon.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
@@ -213,21 +213,21 @@
|
||||
galaxyGroups = [];
|
||||
galaxyRotations = [];
|
||||
|
||||
// 创建9个银河系(合理距离,多种角度)
|
||||
// 创建9个银河系(合理距离,多种角度,大胆倾斜,保持足够距离)
|
||||
const galaxyPositions = [
|
||||
// 中心主银河系
|
||||
// 中心主银河系 - 横着正常显示
|
||||
{ x: 0, y: 0, z: 0, scale: 1.0, rotX: 0, rotZ: 0 },
|
||||
// 前面银河系(z正方向)
|
||||
{ x: 500, y: 200, z: 600, scale: 0.7, rotX: 0.1, rotZ: -0.05 },
|
||||
{ x: -400, y: 350, z: 500, scale: 0.65, rotX: -0.08, rotZ: 0.12 },
|
||||
{ x: 300, y: -250, z: 700, scale: 0.6, rotX: 0.15, rotZ: -0.1 },
|
||||
// 近距离(600-900单位)
|
||||
{ x: 700, y: 200, z: -500, scale: 0.75, rotX: 0.1, rotZ: -0.05 },
|
||||
{ x: -600, y: -350, z: -400, scale: 0.7, rotX: -0.08, rotZ: 0.12 },
|
||||
// 中距离(1000-1500单位)
|
||||
{ x: 1200, y: 500, z: -1000, scale: 0.6, rotX: 0.15, rotZ: -0.1 },
|
||||
{ x: -1100, y: 400, z: -900, scale: 0.55, rotX: -0.12, rotZ: 0.08 },
|
||||
{ x: 400, y: -900, z: -800, scale: 0.65, rotX: 0.05, rotZ: 0.15 },
|
||||
// 前面银河系(z正方向)- 距离主银河系1200+
|
||||
{ x: 900, y: 350, z: 1100, scale: 0.7, rotX: -0.4, rotZ: 0.6 },
|
||||
{ x: -800, y: 600, z: 1000, scale: 0.65, rotX: 0.5, rotZ: -0.3 },
|
||||
{ x: 600, y: -500, z: 1200, scale: 0.6, rotX: -0.7, rotZ: 0.4 },
|
||||
// 近距离(1300-1600单位)
|
||||
{ x: 1300, y: 400, z: -900, scale: 0.75, rotX: 0.8, rotZ: -0.5 },
|
||||
{ x: -1200, y: -600, z: -800, scale: 0.7, rotX: -0.3, rotZ: 0.7 },
|
||||
// 中距离(1800-2200单位)
|
||||
{ x: 2000, y: 800, z: -1700, scale: 0.6, rotX: 0.6, rotZ: -0.8 },
|
||||
{ x: -1900, y: 700, z: -1600, scale: 0.55, rotX: -0.5, rotZ: 0.4 },
|
||||
{ x: 700, y: -1600, z: -1400, scale: 0.65, rotX: 0.9, rotZ: -0.6 },
|
||||
];
|
||||
|
||||
galaxyPositions.forEach((pos, index) => {
|
||||
@@ -307,9 +307,30 @@
|
||||
function createPhotoStar(photo, index, galaxyGroup) {
|
||||
// 创建圆形纹理
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
const texture = textureLoader.load(photo.src);
|
||||
const texture = textureLoader.load(photo.src, (loadedTexture) => {
|
||||
// 图片加载完成后,根据原始比例调整几何体
|
||||
const image = loadedTexture.image;
|
||||
const aspectRatio = image.width / image.height;
|
||||
let width = 30;
|
||||
let height = 30;
|
||||
|
||||
// 创建正方形几何体
|
||||
if (aspectRatio > 1) {
|
||||
// 宽图:宽度为30,高度按比例
|
||||
height = width / aspectRatio;
|
||||
} else {
|
||||
// 高图或正方形:高度为30,宽度按比例
|
||||
height = 30;
|
||||
width = height * aspectRatio;
|
||||
}
|
||||
|
||||
// 更新几何体尺寸
|
||||
star.geometry.dispose();
|
||||
star.geometry = new THREE.PlaneGeometry(width, height);
|
||||
hitArea.geometry.dispose();
|
||||
hitArea.geometry = new THREE.PlaneGeometry(width * 2, height * 2);
|
||||
});
|
||||
|
||||
// 创建默认正方形几何体(加载完成后会被替换)
|
||||
const geometry = new THREE.PlaneGeometry(30, 30);
|
||||
|
||||
// 创建材质 - 无滤镜
|
||||
@@ -323,27 +344,46 @@
|
||||
// 创建网格
|
||||
const star = new THREE.Mesh(geometry, material);
|
||||
|
||||
// 创建一个更大的透明点击检测区域
|
||||
const hitGeometry = new THREE.PlaneGeometry(60, 60);
|
||||
const hitMaterial = new THREE.MeshBasicMaterial({
|
||||
transparent: true,
|
||||
opacity: 0.001, // 几乎透明但不完全透明,以便raycaster能检测到
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const hitArea = new THREE.Mesh(hitGeometry, hitMaterial);
|
||||
|
||||
// 随机位置(银河系分布)
|
||||
const radius = 200 + Math.random() * 600;
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = (Math.random() - 0.5) * Math.PI * 0.3; // 扁平分布
|
||||
|
||||
star.position.x = radius * Math.cos(theta) * Math.cos(phi);
|
||||
star.position.y = radius * Math.sin(phi) * 0.3; // 更扁平
|
||||
star.position.z = radius * Math.sin(theta) * Math.cos(phi);
|
||||
const x = radius * Math.cos(theta) * Math.cos(phi);
|
||||
const y = radius * Math.sin(phi) * 0.3; // 更扁平
|
||||
const z = radius * Math.sin(theta) * Math.cos(phi);
|
||||
|
||||
// 存储照片信息
|
||||
star.userData = {
|
||||
// 设置两个网格的相同位置
|
||||
star.position.set(x, y, z);
|
||||
hitArea.position.set(x, y, z);
|
||||
|
||||
// 存储照片信息(两个网格共享相同的userData)
|
||||
const userData = {
|
||||
photoId: photo.id,
|
||||
photoSrc: photo.src,
|
||||
photoFilename: photo.filename
|
||||
};
|
||||
star.userData = userData;
|
||||
hitArea.userData = userData;
|
||||
|
||||
// 面向相机
|
||||
star.lookAt(camera.position);
|
||||
hitArea.lookAt(camera.position);
|
||||
|
||||
// 将点击检测区域添加到组中
|
||||
galaxyGroup.add(hitArea);
|
||||
galaxyGroup.add(star);
|
||||
stars.push(star);
|
||||
stars.push(hitArea); // 也添加到检测数组中
|
||||
}
|
||||
|
||||
// 创建默认星星
|
||||
@@ -373,21 +413,21 @@
|
||||
|
||||
// 添加装饰性星星(银河系效果)
|
||||
function addDecorativeStars(galaxyGroup, scale = 1, galaxyIndex = 0) {
|
||||
const starCount = Math.floor(4000 * scale); // 根据缩放调整星星数量
|
||||
const starCount = Math.floor(8000 * scale); // 星星数量增加到8000
|
||||
const starGeometry = new THREE.BufferGeometry();
|
||||
const positions = new Float32Array(starCount * 3);
|
||||
const colors = new Float32Array(starCount * 3);
|
||||
const sizes = new Float32Array(starCount);
|
||||
|
||||
// 银河系参数
|
||||
const bulgeRadius = 120; // 银核半径
|
||||
const diskRadius = 700; // 银盘半径
|
||||
const armCount = 4; // 旋臂数量
|
||||
const spiralAngle = 12; // 螺旋角(度)
|
||||
const spiralTightness = 0.005; // 螺旋紧密度
|
||||
const bulgeRadius = 150; // 银核半径
|
||||
const diskRadius = 600; // 银盘半径
|
||||
const armCount = galaxyIndex === 0 ? 4 : (galaxyIndex % 2 === 0 ? 4 : 6); // 主银河4条,其他4或6条
|
||||
const spin = 0.3; // 旋臂旋转角度
|
||||
const radialRandomness = 0.4; // 径向随机性
|
||||
|
||||
// 根据银河系索引选择配色方案
|
||||
const colorScheme = galaxyIndex === 0 ? 'warm' : getColorScheme(galaxyIndex);
|
||||
// 根据银河系索引选择配色方案(主银河系用蓝色调)
|
||||
const colorScheme = galaxyIndex === 0 ? 'blue' : getColorScheme(galaxyIndex);
|
||||
|
||||
// 获取银河系配色方案
|
||||
function getColorScheme(index) {
|
||||
@@ -414,195 +454,157 @@
|
||||
}
|
||||
|
||||
// 根据配色方案获取颜色
|
||||
function getColor(scheme, brightness, distanceFromCenter) {
|
||||
function getColor(scheme, radiusRatio) {
|
||||
let color;
|
||||
const t = radiusRatio; // 0=中心,1=边缘
|
||||
|
||||
switch (scheme) {
|
||||
case 'warm': // 主银河系 - 暖黄色(不淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [1, 0.9 + brightness * 0.1, 0.7 + brightness * 0.3];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [1, 0.8 + Math.random() * 0.15, 0.4 + Math.random() * 0.3];
|
||||
} else {
|
||||
color = [0.9 + Math.random() * 0.1, 0.85 + Math.random() * 0.1, 0.6 + Math.random() * 0.2];
|
||||
}
|
||||
return color; // 主银河系不淡化
|
||||
case 'warm': // 主银河系 - 暖黄色
|
||||
return [1, 0.9 - t * 0.3, 0.6 - t * 0.4]; // 橙到紫
|
||||
|
||||
case 'blue': // 蓝色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.3, 0.5 + brightness * 0.3, 0.9 + brightness * 0.1];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.2 + Math.random() * 0.1, 0.4 + Math.random() * 0.2, 0.8 + Math.random() * 0.15];
|
||||
} else {
|
||||
color = [0.1 + Math.random() * 0.15, 0.3 + Math.random() * 0.2, 0.7 + Math.random() * 0.2];
|
||||
}
|
||||
case 'blue':
|
||||
color = [0.3, 0.5 + t * 0.3, 0.9 - t * 0.2];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'purple': // 紫色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.7 + brightness * 0.3, 0.3, 0.9 + brightness * 0.1];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.6 + Math.random() * 0.2, 0.2 + Math.random() * 0.1, 0.8 + Math.random() * 0.15];
|
||||
} else {
|
||||
color = [0.5 + Math.random() * 0.2, 0.1 + Math.random() * 0.15, 0.7 + Math.random() * 0.2];
|
||||
}
|
||||
case 'purple':
|
||||
color = [0.7 - t * 0.3, 0.3, 0.9 - t * 0.1];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'cyan': // 青色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.2, 0.8 + brightness * 0.2, 0.9 + brightness * 0.1];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.1 + Math.random() * 0.1, 0.7 + Math.random() * 0.15, 0.8 + Math.random() * 0.15];
|
||||
} else {
|
||||
color = [0.05 + Math.random() * 0.1, 0.6 + Math.random() * 0.2, 0.7 + Math.random() * 0.2];
|
||||
}
|
||||
case 'cyan':
|
||||
color = [0.2, 0.8 - t * 0.3, 0.9 - t * 0.2];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'pink': // 粉色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.9 + brightness * 0.1, 0.4 + brightness * 0.2, 0.6 + brightness * 0.2];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.8 + Math.random() * 0.15, 0.3 + Math.random() * 0.15, 0.5 + Math.random() * 0.2];
|
||||
} else {
|
||||
color = [0.7 + Math.random() * 0.2, 0.2 + Math.random() * 0.15, 0.4 + Math.random() * 0.2];
|
||||
}
|
||||
case 'pink':
|
||||
color = [0.9 - t * 0.2, 0.4 + t * 0.1, 0.6 - t * 0.2];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'red': // 红色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.9 + brightness * 0.1, 0.3, 0.3];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.8 + Math.random() * 0.15, 0.2 + Math.random() * 0.1, 0.2 + Math.random() * 0.1];
|
||||
} else {
|
||||
color = [0.7 + Math.random() * 0.2, 0.1 + Math.random() * 0.15, 0.1 + Math.random() * 0.15];
|
||||
}
|
||||
case 'red':
|
||||
color = [0.9 - t * 0.2, 0.3 + t * 0.1, 0.3];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'green': // 绿色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.3, 0.8 + brightness * 0.2, 0.4];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.2 + Math.random() * 0.1, 0.7 + Math.random() * 0.15, 0.3 + Math.random() * 0.1];
|
||||
} else {
|
||||
color = [0.1 + Math.random() * 0.15, 0.6 + Math.random() * 0.2, 0.2 + Math.random() * 0.15];
|
||||
}
|
||||
case 'green':
|
||||
color = [0.3, 0.8 - t * 0.2, 0.4 + t * 0.1];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'orange': // 橙色系(淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.9 + brightness * 0.1, 0.6 + brightness * 0.2, 0.2];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.8 + Math.random() * 0.15, 0.5 + Math.random() * 0.15, 0.15 + Math.random() * 0.1];
|
||||
} else {
|
||||
color = [0.7 + Math.random() * 0.2, 0.4 + Math.random() * 0.2, 0.1 + Math.random() * 0.15];
|
||||
}
|
||||
case 'orange':
|
||||
color = [0.9 - t * 0.2, 0.6 - t * 0.3, 0.2 + t * 0.1];
|
||||
return fadeColor(color, 0.45);
|
||||
|
||||
case 'white': // 白色系(已经是淡色,稍微淡化)
|
||||
if (distanceFromCenter < 0.3) {
|
||||
color = [0.9 + brightness * 0.1, 0.9 + brightness * 0.1, 0.9 + brightness * 0.1];
|
||||
} else if (distanceFromCenter < 0.5) {
|
||||
color = [0.8 + Math.random() * 0.1, 0.8 + Math.random() * 0.1, 0.8 + Math.random() * 0.1];
|
||||
} else {
|
||||
color = [0.7 + Math.random() * 0.15, 0.7 + Math.random() * 0.15, 0.7 + Math.random() * 0.15];
|
||||
}
|
||||
return fadeColor(color, 0.3); // 白色系淡化程度低一些
|
||||
case 'white':
|
||||
color = [0.9 - t * 0.2, 0.9 - t * 0.2, 0.9 - t * 0.2];
|
||||
return fadeColor(color, 0.3);
|
||||
|
||||
default:
|
||||
color = [1, 1, 1];
|
||||
return color;
|
||||
return [1, 0.9 - t * 0.3, 0.6 - t * 0.4];
|
||||
}
|
||||
}
|
||||
|
||||
// 随机极坐标(用于径向偏移)
|
||||
function getRandomPolarCoordinate(radius) {
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = Math.random() * Math.PI * 2;
|
||||
return {
|
||||
x: radius * Math.sin(theta) * Math.cos(phi),
|
||||
y: radius * Math.sin(theta) * Math.sin(phi),
|
||||
z: radius * Math.cos(theta)
|
||||
};
|
||||
}
|
||||
|
||||
for (let i = 0; i < starCount; i++) {
|
||||
let x, y, z, brightness;
|
||||
let x, y, z, brightness, color;
|
||||
|
||||
// 根据概率分配
|
||||
const rand = Math.random();
|
||||
|
||||
if (rand < 0.15) {
|
||||
// ==================== 银核(15%)====================
|
||||
// 非常明亮的圆球区域,大量星星密集分布
|
||||
|
||||
// 使用球形分布,中心密度最高
|
||||
const r = Math.pow(Math.random(), 0.2) * bulgeRadius; // 高度集中在中心
|
||||
if (rand < 0.12) {
|
||||
// ==================== 银核(12%)====================
|
||||
// 非常明亮的圆球区域,厚实密集
|
||||
const r = Math.pow(Math.random(), 0.3) * bulgeRadius;
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
const phi = Math.acos(2 * Math.random() - 1); // 均匀的球形分布
|
||||
const phi = Math.acos(2 * Math.random() - 1);
|
||||
|
||||
x = r * Math.sin(phi) * Math.cos(theta);
|
||||
y = r * Math.cos(phi) * 0.5; // 稍微扁平一些
|
||||
y = r * Math.cos(phi) * 0.6; // 稍微扁平
|
||||
z = r * Math.sin(phi) * Math.sin(theta);
|
||||
|
||||
// 银核非常亮,中心最亮
|
||||
brightness = 0.85 + Math.pow(1 - r / bulgeRadius, 2) * 0.15;
|
||||
sizes[i] = 3 + Math.random() * 4; // 大尺寸的明亮星星
|
||||
sizes[i] = 3 + Math.random() * 5; // 更大尺寸
|
||||
|
||||
} else if (rand < 0.85) {
|
||||
// ==================== 旋臂(70%)====================
|
||||
// 星星严格分布在旋臂上
|
||||
// 银核颜色:暖白色
|
||||
const bulgeColor = getColor(colorScheme, 0);
|
||||
color = [
|
||||
Math.min(1, bulgeColor[0] + 0.2),
|
||||
Math.min(1, bulgeColor[1] + 0.15),
|
||||
Math.min(1, bulgeColor[2] + 0.1)
|
||||
];
|
||||
|
||||
} else if (rand < 0.30) {
|
||||
// ==================== 旋臂上(18%)====================
|
||||
// 参考 test.html 的旋臂算法
|
||||
|
||||
// 选择一条旋臂
|
||||
const armIndex = Math.floor(Math.random() * armCount);
|
||||
const armBaseAngle = (armIndex / armCount) * Math.PI * 2;
|
||||
const armIndex = i % armCount;
|
||||
const branchAngle = (armIndex / armCount) * Math.PI * 2;
|
||||
|
||||
// 从银核向外延伸的距离
|
||||
const distance = bulgeRadius + Math.pow(Math.random(), 0.6) * (diskRadius - bulgeRadius);
|
||||
// 从银核向外的距离
|
||||
const radius = bulgeRadius + Math.random() * (diskRadius - bulgeRadius);
|
||||
|
||||
// 螺旋线角度
|
||||
const spiralTheta = armBaseAngle + spiralTightness * distance * Math.log(1 + distance / bulgeRadius);
|
||||
// 旋臂旋转角度(距离越远旋转越多)
|
||||
const spinAngle = spin * radius * 0.01;
|
||||
|
||||
// 旋臂宽度(更粗壮)
|
||||
const armWidth = 880 + distance * 0.12;
|
||||
|
||||
// 高斯分布让星星集中在旋臂中心
|
||||
const gaussianRandom = (Math.random() + Math.random() + Math.random()) / 3 - 0.5;
|
||||
const offset = gaussianRandom * armWidth * 0.5;
|
||||
// 径向随机偏移(让旋臂更粗壮)
|
||||
const randRadius = Math.random() * radialRandomness * radius * 0.5;
|
||||
const randOffset = getRandomPolarCoordinate(randRadius);
|
||||
|
||||
// 计算位置
|
||||
const angle = spiralTheta;
|
||||
x = distance * Math.cos(angle) + offset * Math.cos(angle + Math.PI / 2);
|
||||
z = distance * Math.sin(angle) + offset * Math.sin(angle + Math.PI / 2);
|
||||
x = radius * Math.cos(branchAngle + spinAngle) + randOffset.x;
|
||||
z = radius * Math.sin(branchAngle + spinAngle) + randOffset.z;
|
||||
y = randOffset.y * 0.3; // 扁平分布
|
||||
|
||||
// 高度分布(扁平)
|
||||
y = (Math.random() - 0.5) * 15 * (distance / diskRadius);
|
||||
// 亮度随距离衰减
|
||||
const radiusRatio = (radius - bulgeRadius) / (diskRadius - bulgeRadius);
|
||||
brightness = Math.max(0.5, 1 - radiusRatio * 0.4);
|
||||
sizes[i] = 1.5 + Math.random() * 2.5;
|
||||
|
||||
// 旋臂较亮
|
||||
brightness = Math.max(0.6, 1 - distance / diskRadius * 0.3);
|
||||
sizes[i] = 1.5 + Math.random() * 2;
|
||||
// 颜色从内到外渐变
|
||||
color = getColor(colorScheme, radiusRatio);
|
||||
|
||||
} else {
|
||||
// ==================== 背景星星(30%)====================
|
||||
// 随机分布,但避开旋臂区域(相对稀疏)
|
||||
// ==================== 旋臂之间(70%)====================
|
||||
// 随机分布在银盘上,不在旋臂上
|
||||
|
||||
const distance = bulgeRadius + Math.random() * (diskRadius - bulgeRadius);
|
||||
// 从银核向外的距离
|
||||
const radius = bulgeRadius + Math.random() * (diskRadius - bulgeRadius);
|
||||
|
||||
// 随机角度(不跟随旋臂)
|
||||
const theta = Math.random() * Math.PI * 2;
|
||||
|
||||
x = distance * Math.cos(theta);
|
||||
z = distance * Math.sin(theta);
|
||||
y = (Math.random() - 0.5) * 50; // 扁平分布
|
||||
// 随机偏移
|
||||
const randOffset = getRandomPolarCoordinate(radius * 0.15);
|
||||
|
||||
// 背景较暗
|
||||
brightness = Math.max(0.2, 0.5 - distance / diskRadius * 0.3);
|
||||
sizes[i] = 0.5 + Math.random() * 1;
|
||||
// 计算位置
|
||||
x = radius * Math.cos(theta) + randOffset.x;
|
||||
z = radius * Math.sin(theta) + randOffset.z;
|
||||
y = (Math.random() - 0.5) * 20; // 扁平分布
|
||||
|
||||
// 背景星星亮度提高,但不超过旋臂
|
||||
const radiusRatio = (radius - bulgeRadius) / (diskRadius - bulgeRadius);
|
||||
brightness = Math.max(0.45, 0.75 - radiusRatio * 0.3);
|
||||
sizes[i] = 0.8 + Math.random() * 1.5; // 较小尺寸
|
||||
|
||||
// 颜色从内到外渐变,亮度提高但仍比旋臂暗
|
||||
color = getColor(colorScheme, radiusRatio);
|
||||
color[0] *= 0.75;
|
||||
color[1] *= 0.75;
|
||||
color[2] *= 0.75;
|
||||
}
|
||||
|
||||
positions[i * 3] = x;
|
||||
positions[i * 3 + 1] = y;
|
||||
positions[i * 3 + 2] = z;
|
||||
|
||||
// 设置颜色(根据配色方案)
|
||||
const distanceFromCenter = Math.sqrt(x * x + y * y + z * z) / bulgeRadius;
|
||||
const color = getColor(colorScheme, brightness, distanceFromCenter);
|
||||
colors[i * 3] = color[0];
|
||||
colors[i * 3 + 1] = color[1];
|
||||
colors[i * 3 + 2] = color[2];
|
||||
|
||||
// 背景星星用冷色调(除了主银河系)
|
||||
if (rand >= 0.70 && galaxyIndex !== 0) {
|
||||
colors[i * 3] *= 0.5;
|
||||
colors[i * 3 + 1] *= 0.5;
|
||||
colors[i * 3 + 2] *= 0.5;
|
||||
}
|
||||
colors[i * 3] = color[0] * brightness;
|
||||
colors[i * 3 + 1] = color[1] * brightness;
|
||||
colors[i * 3 + 2] = color[2] * brightness;
|
||||
|
||||
sizes[i] *= brightness;
|
||||
}
|
||||
@@ -623,61 +625,131 @@
|
||||
const starField = new THREE.Points(starGeometry, starMaterial);
|
||||
galaxyGroup.add(starField);
|
||||
|
||||
// 添加银核发光球体
|
||||
addGalacticCore(galaxyGroup, scale);
|
||||
// 添加银核发光球体(使用不同的行星样式)
|
||||
addGalacticCore(galaxyGroup, scale, galaxyIndex);
|
||||
|
||||
// 添加星云效果
|
||||
addNebulaEffect(galaxyGroup, scale);
|
||||
addNebulaEffect(galaxyGroup, scale, galaxyIndex, colorScheme);
|
||||
}
|
||||
|
||||
// 添加银核发光球体
|
||||
function addGalacticCore(galaxyGroup, scale = 1) {
|
||||
// 创建一个明亮的发光球体作为银核
|
||||
const coreGeometry = new THREE.SphereGeometry(80, 32, 32);
|
||||
const coreMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0xFFF5E1, // 暖白色
|
||||
function addGalacticCore(galaxyGroup, scale = 1, galaxyIndex = 0) {
|
||||
if (galaxyIndex === 0) {
|
||||
// 主银河系 - 使用地球纹理
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
const earthTexture = textureLoader.load('./static/img/planets/earth.jpg');
|
||||
|
||||
// 创建地球球体
|
||||
const earthGeometry = new THREE.SphereGeometry(100, 64, 64);
|
||||
const earthMaterial = new THREE.MeshBasicMaterial({
|
||||
map: earthTexture,
|
||||
transparent: true,
|
||||
opacity: 0.95,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const earthMesh = new THREE.Mesh(earthGeometry, earthMaterial);
|
||||
galaxyGroup.add(earthMesh);
|
||||
|
||||
// 添加蓝色发光效果层
|
||||
const glowGeometry = new THREE.SphereGeometry(110, 32, 32);
|
||||
const glowMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0x4169E1, // 蓝色光晕
|
||||
transparent: true,
|
||||
opacity: 0.3,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const glowMesh = new THREE.Mesh(glowGeometry, glowMaterial);
|
||||
galaxyGroup.add(glowMesh);
|
||||
|
||||
// 创建月球
|
||||
const moonTexture = textureLoader.load('./static/img/planets/moon.jpg');
|
||||
const moonGeometry = new THREE.SphereGeometry(25, 32, 32);
|
||||
const moonMaterial = new THREE.MeshBasicMaterial({
|
||||
map: moonTexture,
|
||||
transparent: true,
|
||||
opacity: 0.9,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const moonMesh = new THREE.Mesh(moonGeometry, moonMaterial);
|
||||
// 初始位置(离地球更远)
|
||||
moonMesh.position.set(250, 0, 0);
|
||||
galaxyGroup.add(moonMesh);
|
||||
|
||||
// 存储地球和月球引用用于动画
|
||||
galaxyGroup.userData = {
|
||||
earth: earthMesh,
|
||||
earthRotation: 0,
|
||||
moon: moonMesh,
|
||||
moonAngle: 0,
|
||||
moonRotation: 0
|
||||
};
|
||||
} else {
|
||||
// 其他银河系 - 白色圆球
|
||||
// 外层白色球体
|
||||
const coreGeometry = new THREE.SphereGeometry(100, 32, 32);
|
||||
const coreMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0xFFFFFF,
|
||||
transparent: true,
|
||||
opacity: 0.35,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const coreMesh = new THREE.Mesh(coreGeometry, coreMaterial);
|
||||
galaxyGroup.add(coreMesh);
|
||||
|
||||
// 添加第二层发光(更亮更小)
|
||||
const innerCoreGeometry = new THREE.SphereGeometry(40, 32, 32);
|
||||
// 中层更亮
|
||||
const innerCoreGeometry = new THREE.SphereGeometry(55, 32, 32);
|
||||
const innerCoreMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0xFFFBE6, // 更亮的白色
|
||||
color: 0xFFFFFF,
|
||||
transparent: true,
|
||||
opacity: 0.5,
|
||||
opacity: 0.55,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const innerCoreMesh = new THREE.Mesh(innerCoreGeometry, innerCoreMaterial);
|
||||
galaxyGroup.add(innerCoreMesh);
|
||||
|
||||
// 添加核心光点(最亮)
|
||||
const coreLightGeometry = new THREE.SphereGeometry(15, 32, 32);
|
||||
// 核心光点
|
||||
const coreLightGeometry = new THREE.SphereGeometry(20, 32, 32);
|
||||
const coreLightMaterial = new THREE.MeshBasicMaterial({
|
||||
color: 0xFFFFF0, // 纯白偏黄
|
||||
color: 0xFFFFFF,
|
||||
transparent: true,
|
||||
opacity: 0.7,
|
||||
opacity: 0.8,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
const coreLightMesh = new THREE.Mesh(coreLightGeometry, coreLightMaterial);
|
||||
galaxyGroup.add(coreLightMesh);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加星云效果
|
||||
function addNebulaEffect(galaxyGroup, scale = 1) {
|
||||
function addNebulaEffect(galaxyGroup, scale = 1, galaxyIndex = 0, colorScheme = 'blue') {
|
||||
const nebulaCount = Math.floor(80 * scale); // 根据缩放调整数量
|
||||
const armCount = galaxyIndex === 0 ? 4 : (galaxyIndex % 2 === 0 ? 4 : 6);
|
||||
const nebulaGeometry = new THREE.BufferGeometry();
|
||||
const nebulaPositions = new Float32Array(nebulaCount * 3);
|
||||
const nebulaColors = new Float32Array(nebulaCount * 3);
|
||||
const nebulaSizes = new Float32Array(nebulaCount);
|
||||
|
||||
// 根据配色方案获取星云基础颜色
|
||||
function getNebulaBaseColor(scheme) {
|
||||
switch (scheme) {
|
||||
case 'blue': return [0.4, 0.6, 1.0];
|
||||
case 'purple': return [0.7, 0.4, 1.0];
|
||||
case 'cyan': return [0.3, 0.9, 1.0];
|
||||
case 'pink': return [1.0, 0.5, 0.7];
|
||||
case 'red': return [1.0, 0.4, 0.4];
|
||||
case 'green': return [0.4, 0.9, 0.5];
|
||||
case 'orange': return [1.0, 0.7, 0.3];
|
||||
case 'white': return [0.9, 0.9, 0.9];
|
||||
default: return [0.9, 0.7, 0.3];
|
||||
}
|
||||
}
|
||||
|
||||
const baseColor = getNebulaBaseColor(colorScheme);
|
||||
|
||||
for (let i = 0; i < nebulaCount; i++) {
|
||||
// 主要分布在旋臂区域
|
||||
const armIndex = Math.floor(Math.random() * 4);
|
||||
const armAngle = (armIndex / 4) * Math.PI * 2;
|
||||
const armIndex = Math.floor(Math.random() * armCount);
|
||||
const armAngle = (armIndex / armCount) * Math.PI * 2;
|
||||
const r = 150 + Math.pow(Math.random(), 0.3) * 500;
|
||||
|
||||
const spiralTightness = 0.12;
|
||||
@@ -688,10 +760,10 @@
|
||||
nebulaPositions[i * 3 + 1] = (Math.random() - 0.5) * 20;
|
||||
nebulaPositions[i * 3 + 2] = r * Math.sin(theta) + offset * Math.sin(theta + Math.PI / 2);
|
||||
|
||||
// 暖黄色星云(金黄色,与银河系协调)
|
||||
nebulaColors[i * 3] = 0.9 + Math.random() * 0.1;
|
||||
nebulaColors[i * 3 + 1] = 0.7 + Math.random() * 0.2;
|
||||
nebulaColors[i * 3 + 2] = 0.3 + Math.random() * 0.2;
|
||||
// 使用银河系配色,带轻微随机变化
|
||||
nebulaColors[i * 3] = baseColor[0] * (0.8 + Math.random() * 0.4);
|
||||
nebulaColors[i * 3 + 1] = baseColor[1] * (0.8 + Math.random() * 0.4);
|
||||
nebulaColors[i * 3 + 2] = baseColor[2] * (0.8 + Math.random() * 0.4);
|
||||
|
||||
nebulaSizes[i] = 15 + Math.random() * 25;
|
||||
}
|
||||
@@ -881,6 +953,25 @@
|
||||
galaxyGroups.forEach((galaxyGroup, index) => {
|
||||
galaxyRotations[index] += 0.0001 + index * 0.00005; // 不同的旋转速度
|
||||
galaxyGroup.rotation.y = galaxyRotations[index];
|
||||
|
||||
// 月球围绕地球旋转
|
||||
if (galaxyGroup.userData && galaxyGroup.userData.moon) {
|
||||
galaxyGroup.userData.moonAngle += 0.001; // 公转速度(更慢)
|
||||
galaxyGroup.userData.moonRotation += 0.005; // 自转速度(更慢)
|
||||
const moonAngle = galaxyGroup.userData.moonAngle;
|
||||
const moonRadius = 250; // 月球轨道半径(更远)
|
||||
galaxyGroup.userData.moon.position.x = Math.cos(moonAngle) * moonRadius;
|
||||
galaxyGroup.userData.moon.position.z = Math.sin(moonAngle) * moonRadius;
|
||||
galaxyGroup.userData.moon.position.y = Math.sin(moonAngle * 0.5) * 30; // 轻微上下浮动
|
||||
// 月球自转
|
||||
galaxyGroup.userData.moon.rotation.y = galaxyGroup.userData.moonRotation;
|
||||
}
|
||||
|
||||
// 地球自转
|
||||
if (galaxyGroup.userData && galaxyGroup.userData.earth) {
|
||||
galaxyGroup.userData.earthRotation += 0.002; // 地球自转速度(缓慢)
|
||||
galaxyGroup.userData.earth.rotation.y = galaxyGroup.userData.earthRotation;
|
||||
}
|
||||
});
|
||||
|
||||
// 更新相机位置
|
||||
|
||||
Reference in New Issue
Block a user