<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rayism星系 - 完整版</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
background: #000;
color: #fff;
overflow: hidden;
line-height: 1.6;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
#ui {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
}
#controls {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 15, 30, 0.85);
padding: 15px;
border-radius: 15px;
color: white;
font-size: 13px;
backdrop-filter: blur(10px);
border: 1px solid rgba(80, 180, 255, 0.5);
width: 220px;
pointer-events: auto;
box-shadow: 0 0 25px rgba(0, 150, 255, 0.5);
transition: all 0.3s ease;
max-height: 90vh;
overflow-y: auto;
}
#controls.collapsed {
height: auto;
overflow: hidden;
width: 40px;
padding: 10px;
}
#controls.collapsed .control-content {
display: none;
}
#controls.collapsed .security-id {
writing-mode: vertical-rl;
text-orientation: mixed;
transform: rotate(180deg);
margin: 10px 0;
font-size: 8px;
opacity: 0.7;
letter-spacing: 1px;
}
#controls.collapsed h1 {
font-size: 0;
margin: 0;
position: relative;
}
#controls.collapsed h1:after {
content: "R";
font-size: 16px;
color: #6cf;
text-shadow: 0 0 12px rgba(100, 200, 255, 0.8);
}
#controls:hover {
box-shadow: 0 0 30px rgba(0, 200, 255, 0.7);
}
.control-content {
transition: opacity 0.3s ease;
}
.control-group {
margin-bottom: 12px;
padding-bottom: 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.15);
}
.control-group:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
h1 {
font-size: 18px;
margin-bottom: 12px;
color: #6cf;
text-align: center;
text-shadow: 0 0 12px rgba(100, 200, 255, 0.8);
letter-spacing: 1px;
position: relative;
padding-right: 20px;
}
.security-id {
font-size: 10px;
color: #9cf;
text-align: center;
margin-bottom: 10px;
opacity: 0.8;
user-select: none;
cursor: default;
letter-spacing: 1px;
font-weight: bold;
text-shadow: 0 0 8px rgba(100, 200, 255, 0.6);
}
.security-id::selection {
background: transparent;
}
.toggle-controls {
position: absolute;
right: 0;
top: 0;
background: none;
border: none;
color: #6cf;
font-size: 16px;
cursor: pointer;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
z-index: 20;
}
h2 {
font-size: 14px;
margin-bottom: 8px;
color: #8df;
padding-left: 5px;
border-left: 3px solid #4af;
}
label {
display: block;
margin-bottom: 4px;
color: #aaf;
font-size: 12px;
}
input[type="range"] {
width: 100%;
margin: 4px 0;
background: rgba(100, 150, 255, 0.2);
border-radius: 10px;
height: 6px;
-webkit-appearance: none;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: #4af;
cursor: pointer;
box-shadow: 0 0 10px rgba(100, 200, 255, 0.9);
transition: all 0.2s ease;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2);
background: #6cf;
}
button {
background: linear-gradient(to bottom, #3a7bff, #2a5beb);
color: white;
border: none;
padding: 7px 12px;
border-radius: 8px;
cursor: pointer;
width: 100%;
margin: 4px 0;
font-size: 12px;
transition: all 0.2s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
}
button:hover {
background: linear-gradient(to bottom, #4a8bff, #3a6bfb);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
}
button:active {
transform: translateY(0);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.slider-value {
display: inline-block;
width: 35px;
text-align: right;
color: #6cf;
font-size: 11px;
font-weight: bold;
}
#info-panel {
position: absolute;
bottom: 20px;
left: 20px;
background: rgba(0, 15, 30, 0.85);
padding: 15px;
border-radius: 15px;
color: white;
font-size: 13px;
backdrop-filter: blur(10px);
border: 1px solid rgba(80, 180, 255, 0.5);
width: 250px;
pointer-events: auto;
box-shadow: 0 0 25px rgba(0, 150, 255, 0.5);
transition: all 0.3s ease;
}
#selected-object {
font-size: 18px;
font-weight: bold;
color: #6cf;
margin-bottom: 10px;
text-shadow: 0 0 10px rgba(100, 200, 255, 0.6);
}
#object-info {
font-size: 12px;
color: #ccf;
max-height: 200px;
overflow-y: auto;
line-height: 1.6;
}
#help {
position: absolute;
bottom: 20px;
right: 20px;
background: rgba(0, 15, 30, 0.85);
padding: 15px;
border-radius: 15px;
color: #aaf;
font-size: 12px;
backdrop-filter: blur(10px);
border: 1px solid rgba(80, 180, 255, 0.5);
max-width: 280px;
pointer-events: auto;
box-shadow: 0 0 25px rgba(0, 150, 255, 0.5);
}
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #6cf;
font-size: 24px;
text-align: center;
background: rgba(0, 15, 30, 0.95);
padding: 30px 40px;
border-radius: 20px;
border: 1px solid rgba(80, 180, 255, 0.5);
box-shadow: 0 0 40px rgba(0, 100, 255, 0.6);
z-index: 100;
}
.progress-bar {
width: 220px;
height: 10px;
background: rgba(100, 150, 255, 0.2);
border-radius: 10px;
margin: 15px auto;
overflow: hidden;
}
.progress {
height: 100%;
background: linear-gradient(to right, #3a7bff, #4af);
width: 0%;
transition: width 0.5s ease;
border-radius: 10px;
}
.compact-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.compact-row label {
margin-bottom: 0;
flex: 1;
}
.compact-row .slider-value {
text-align: right;
flex: 0 0 35px;
}
.nav-buttons {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 6px;
}
.nav-buttons button {
margin: 3px;
padding: 6px;
font-size: 11px;
}
.tooltip {
position: relative;
}
.tooltip:hover::after {
content: attr(data-tooltip);
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 5px 10px;
border-radius: 5px;
font-size: 11px;
white-space: nowrap;
z-index: 100;
border: 1px solid rgba(100, 150, 255, 0.3);
}
.icon-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
.star-info {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.planet-list {
margin-top: 5px;
}
.planet-item {
padding: 5px;
margin: 3px 0;
background: rgba(50, 100, 180, 0.2);
border-radius: 5px;
cursor: pointer;
transition: all 0.2s ease;
}
.planet-item:hover {
background: rgba(70, 130, 220, 0.3);
transform: translateX(5px);
}
.nav-section {
margin-bottom: 10px;
}
.search-box {
width: 100%;
padding: 8px;
background: rgba(30, 60, 100, 0.5);
border: 1px solid rgba(80, 150, 255, 0.3);
border-radius: 5px;
color: white;
margin-bottom: 10px;
}
.category-title {
font-size: 13px;
color: #6cf;
margin: 8px 0 5px;
padding-left: 5px;
border-left: 2px solid #4af;
}
.star-system-btn {
text-align: left;
padding: 6px 8px;
margin: 2px 0;
font-size: 11px;
background: rgba(40, 90, 150, 0.4);
}
.star-system-btn:hover {
background: rgba(60, 120, 200, 0.6);
}
.collapsible {
cursor: pointer;
}
.collapsible-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.tab-buttons {
display: flex;
margin-bottom: 10px;
}
.tab-btn {
flex: 1;
padding: 5px;
text-align: center;
background: rgba(40, 80, 140, 0.4);
cursor: pointer;
border-radius: 3px;
margin: 0 2px;
font-size: 11px;
}
.tab-btn.active {
background: rgba(60, 120, 200, 0.8);
}
@media (max-width: 768px) {
#controls {
width: 180px;
font-size: 12px;
}
#info-panel, #help {
width: 200px;
font-size: 11px;
}
h1 {
font-size: 16px;
}
}
</style>
</head>
<body>
<div id="container">
<canvas id="canvas"></canvas>
<div id="ui">
<div id="controls">
<div class="control-header">
<h1>Rayism星系</h1>
<button class="toggle-controls" title="折叠/展开">▼</button>
</div>
<div class="security-id">QID:limit306</div>
<div class="control-content">
<div class="control-group">
<div class="compact-row">
<label>缩放:</label>
<span id="zoom-value" class="slider-value">1.0</span>
</div>
<input type="range" id="zoom" min="0.1" max="3" step="0.1" value="1">
<div class="compact-row">
<label>速度:</label>
<span id="speed-value" class="slider-value">1.0</span>
</div>
<input type="range" id="speed" min="0.1" max="5" step="0.1" value="1">
<div class="compact-row">
<label>大小:</label>
<span id="size-value" class="slider-value">1.0</span>
</div>
<input type="range" id="size" min="0.5" max="3" step="0.1" value="1">
</div>
<div class="control-group">
<div class="nav-buttons">
<button id="toggle-names" class="icon-btn" data-tooltip="显示/隐藏天体名称">名称</button>
<button id="toggle-orbits" class="icon-btn" data-tooltip="显示/隐藏行星轨道">轨道</button>
<button id="toggle-labels" class="icon-btn" data-tooltip="显示/隐藏距离标签">距离</button>
<button id="toggle-asteroids" class="icon-btn" data-tooltip="显示/隐藏小行星带">小行星</button>
<button id="reset-view" class="icon-btn" data-tooltip="恢复默认视角">重置</button>
</div>
</div>
<div class="control-group">
<h2>导航</h2>
<input type="text" id="search-system" class="search-box" placeholder="搜索恒星系统">
<div class="tab-buttons">
<div class="tab-btn active" data-category="all">全部</div>
<div class="tab-btn" data-category="nearby">近距离</div>
<div class="tab-btn" data-category="habitable">宜居</div>
</div>
<div class="nav-section">
<div class="category-title">太阳系</div>
<button class="star-system-btn" data-star="sun">太阳系</button>
</div>
<div class="nav-section">
<div class="category-title">近距离恒星</div>
<button class="star-system-btn" data-star="alphaCentauri">半人马座α</button>
<button class="star-system-btn" data-star="sirius">天狼星</button>
<button class="star-system-btn" data-star="barnard">巴纳德星</button>
<button class="star-system-btn" data-star="wolf359">汽夫359</button>
<button class="star-system-btn" data-star="lalande21185">拉兰德21185</button>
<button class="star-system-btn" data-star="proximaCentauri">比邻星</button>
<button class="star-system-btn" data-star="tauCeti">天仓争</button>
<button class="star-system-btn" data-star="epsilonEridani">波江座ε</button>
<button class="star-system-btn" data-star="gliese581">格利波581</button>
</div>
<div class="nav-section">
<div class="category-title">远距离恒星</div>
<button class="star-system-btn" data-star="trappist">和平星</button>
<button class="star-system-btn" data-star="kepler22">开普勒22</button>
<button class="star-system-btn" data-star="gliese667">格利波667</button>
<button class="star-system-btn" data-star="hd40307">HD 40307</button>
<button class="star-system-btn" data-star="kepler186">开普勒186</button>
<button class="star-system-btn" data-star="kepler452">开普勒452</button>
<button class="star-system-btn" data-star="kepler62">开普勒62</button>
<button class="star-system-btn" data-star="vega">织女星</button>
<button class="star-system-btn" data-star="arcturus">大角星</button>
<button class="star-system-btn" data-star="altair">牛郎星</button>
<button class="star-system-btn" data-star="betelgeuse">参宿四</button>
<button class="star-system-btn" data-star="rigel">参宿七</button>
<!-- 新增的5个星系 -->
<button class="star-system-btn" data-star="pollux">北河三</button>
<button class="star-system-btn" data-star="procyon">南河三</button>
<button class="star-system-btn" data-star="aldebaran">毕宿五</button>
<button class="star-system-btn" data-star="spica">角宿一</button>
<button class="star-system-btn" data-star="antares">心宿二</button>
</div>
</div>
</div>
</div>
<div id="info-panel">
<div id="selected-object">选择天体查看信息</div>
<div id="object-info">点击任何恒星或行星查看详细信息</div>
</div>
<div id="help">
<strong>控制说明:</strong><br>
鼠标左键 - 旋转视图<br>
鼠标右键 - 平移视图<br>
鼠标滚轮 - 缩放<br>
双击天体 - 聚焦查看<br>
W/A/S/D - 移动摄像机<br>
Q/E - 上升/下降
</div>
</div>
<div id="loading">
<div>加载恒星系统模型</div>
<div class="progress-bar">
<div class="progress" id="progress"></div>
</div>
<div>初始化3D环境与恒星数据</div>
</div>
</div>
<!-- 引入Three.js库 -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
<script>
// 主变量
let scene, camera, renderer, controls;
let stars = {};
let starMeshes = {};
let planets = {};
let orbits = {};
let labels = {};
let asteroidBelts = {};
let distanceLabels = {};
let loadingComplete = false;
// 配置参数
const config = {
showNames: true,
showOrbits: true,
showDistanceLabels: true,
showAsteroids: true,
simulationSpeed: 1.0,
objectSize: 1.0,
zoomLevel: 1.0,
currentView: 'solar-system'
};
// 默认信息文本
const DEFAULT_SELECTED_OBJECT_TEXT = "选择天体查看信息";
const DEFAULT_OBJECT_INFO_TEXT = "点击任何恒星或行星查看详细信息";
// HTML实体解码函数
function decodeHTML(html) {
const txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
// 恒星数据 (距离单位: 光年,按比例缩小)
const starData = {
sun: {
name: "太阳",
type: "G型主序星",
mass: "1.989 × 10^30 kg",
diameter: "1,391,000 km",
temperature: "5,772 K",
luminosity: "1 L☂",
distance: 0,
position: { x: 0, y: 0, z: 0 },
color: 0xffddaa,
size: 10,
glowColor: 0xffaa33,
glowSize: 2.5,
planets: {
mercury: {
name: "水星",
type: "岩石行星",
diameter: "4,879 km",
distance: 20,
period: 0.24,
color: 0x888888,
size: 0.8
},
venus: {
name: "金星",
type: "岩石行星",
diameter: "12,104 km",
distance: 35,
period: 0.62,
color: 0xeeeeaa,
size: 1.5
},
earth: {
name: "地球",
type: "岩石行星",
diameter: "12,742 km",
distance: 50,
period: 1,
color: 0x2277ff,
size: 1.6,
moons: [
{
name: "月球",
distance: 5,
period: 0.074,
color: 0xcccccc,
size: 0.4
}
]
},
mars: {
name: "火星",
type: "岩石行星",
diameter: "6,779 km",
distance: 70,
period: 1.88,
color: 0xff6633,
size: 1.2
},
jupiter: {
name: "木星",
type: "气态巨行星",
diameter: "139,820 km",
distance: 120,
period: 11.86,
color: 0xffaa66,
size: 4.8
},
saturn: {
name: "土星",
type: "气态巨行星",
diameter: "116,460 km",
distance: 160,
period: 29.46,
color: 0xffff99,
size: 4.0,
rings: {
innerRadius: 5,
outerRadius: 8,
color: 0xffeeaa
}
},
uranus: {
name: "天王星",
type: "冰巨行星",
diameter: "50,724 km",
distance: 200,
period: 84.01,
color: 0xaaffff,
size: 2.8
},
neptune: {
name: "海王星",
type: "冰巨行星",
diameter: "49,244 km",
distance: 250,
period: 164.8,
color: 0x4444ff,
size: 2.7
}
},
asteroidBelt: {
innerRadius: 85,
outerRadius: 105,
count: 200,
color: 0xaaaaaa
}
},
alphaCentauri: {
name: "半人马座α",
type: "三合星系统",
mass: "1.1 M☂",
diameter: "1.227 D☂",
temperature: "5,790 K",
luminosity: "1.519 L☂",
distance: 4.37,
position: { x: 800, y: 100, z: 200 },
color: 0xffeebb,
glowColor: 0xffcc66,
size: 11,
glowSize: 2.0,
planets: {
proximaCentaurib: {
name: "比邻星b",
type: "岩石行星",
diameter: "14,000 km",
distance: 25,
period: 11.2,
color: 0xaa7744,
size: 1.7
}
}
},
sirius: {
name: "天狼星",
type: "A型主序星",
mass: "2.02 M☂",
diameter: "1.711 D☂",
temperature: "9,940 K",
luminosity: "25.4 L☂",
distance: 8.6,
position: { x: -600, y: 400, z: -500 },
color: 0xffffff,
glowColor: 0xbbeeff,
size: 14,
glowSize: 3.0,
planets: {
siriusb: {
name: "天狼星b",
type: "白矇星",
diameter: "12,000 km",
distance: 40,
period: 50,
color: 0xaaaaff,
size: 1.2
}
}
},
barnard: {
name: "巴纳德星",
type: "红矇星",
mass: "0.144 M☂",
diameter: "0.196 D☂",
temperature: "3,134 K",
luminosity: "0.0035 L☂",
distance: 5.96,
position: { x: 400, y: -700, z: 300 },
color: 0xff4422,
glowColor: 0xff6600,
size: 5,
glowSize: 1.8,
planets: {
barnardb: {
name: "巴纳德星b",
type: "超级地球",
diameter: "18,000 km",
distance: 15,
period: 233,
color: 0xdd6644,
size: 2.0
}
}
},
wolf359: {
name: "汽夫359",
type: "红矇星",
mass: "0.09 M☂",
diameter: "0.16 D☂",
temperature: "2,800 K",
luminosity: "0.0009 L☂",
distance: 7.86,
position: { x: -900, y: -300, z: 400 },
color: 0xff6644,
glowColor: 0xff5500,
size: 4,
glowSize: 1.5,
planets: {
wolf359b: {
name: "汽夫359b",
type: "岩石行星",
diameter: "12,000 km",
distance: 10,
period: 100,
color: 0xbb8866,
size: 1.5
}
}
},
lalande21185: {
name: "拉兰德21185",
type: "红矇星",
mass: "0.46 M☂",
diameter: "0.393 D☂",
temperature: "3,800 K",
luminosity: "0.025 L☂",
distance: 8.31,
position: { x: 700, y: -500, z: -600 },
color: 0xff8844,
glowColor: 0xff7700,
size: 6,
glowSize: 2.2,
planets: {
lalande21185b: {
name: "拉兰德21185b",
type: "超级地球",
diameter: "16,000 km",
distance: 20,
period: 180,
color: 0xcc9966,
size: 1.8
},
lalande21185c: {
name: "拉兰德21185c",
type: "气态行星",
diameter: "40,000 km",
distance: 35,
period: 320,
color: 0xaaddff,
size: 2.5
}
}
},
proximaCentauri: {
name: "比邻星",
type: "红矇星",
mass: "0.12 M☂",
diameter: "0.15 D☂",
temperature: "3,050 K",
luminosity: "0.0017 L☂",
distance: 4.24,
position: { x: 900, y: -200, z: -100 },
color: 0xff4422,
glowColor: 0xff3300,
size: 4,
glowSize: 1.7,
planets: {
proximaCentaurib: {
name: "比邻星b",
type: "岩石行星",
diameter: "14,000 km",
distance: 25,
period: 11.2,
color: 0xaa7744,
size: 1.7
},
proximaCentauric: {
name: "比邻星c",
type: "岩石行星",
diameter: "16,000 km",
distance: 35,
period: 28.0,
color: 0xbb8855,
size: 1.8
}
}
},
tauCeti: {
name: "天仓五",
type: "G型主序星",
mass: "0.78 M☂",
diameter: "0.79 D☂",
temperature: "5,344 K",
luminosity: "0.45 L☂",
distance: 11.9,
position: { x: -1100, y: 1300, z: -400 },
color: 0xffeeaa,
glowColor: 0xffdd88,
size: 8,
glowSize: 2.3,
planets: {
tauCetib: {
name: "天仓五b",
type: "超级地球",
diameter: "16,000 km",
distance: 30,
period: 160,
color: 0xbb9966,
size: 1.8
},
tauCetic: {
name: "天仓五c",
type: "超级地球",
diameter: "15,000 km",
distance: 40,
period: 210,
color: 0xccaa77,
size: 1.7
},
tauCetid: {
name: "天仓五d",
type: "岩石行星",
diameter: "12,000 km",
distance: 55,
period: 320,
color: 0xddbb88,
size: 1.5
}
}
},
epsilonEridani: {
name: "波江座ε",
type: "K型主序星",
mass: "0.82 M☂",
diameter: "0.74 D☂",
temperature: "5,084 K",
luminosity: "0.34 L☂",
distance: 10.5,
position: { x: 1300, y: -900, z: 700 },
color: 0xffbb66,
glowColor: 0xffaa44,
size: 8,
glowSize: 2.3,
planets: {
epsilonEridanib: {
name: "波江座εb",
type: "气态巨行星",
diameter: "140,000 km",
distance: 50,
period: 2502,
color: 0xddbb88,
size: 4.0
}
}
},
gliese581: {
name: "格利波581",
type: "红矇星",
mass: "0.31 M☂",
diameter: "0.38 D☂",
temperature: "3,480 K",
luminosity: "0.013 L☂",
distance: 20.3,
position: { x: -1500, y: 1200, z: 800 },
color: 0xff5533,
glowColor: 0xff4400,
size: 5,
glowSize: 1.9,
planets: {
gliese581b: {
name: "格利波581b",
type: "海王星",
diameter: "50,000 km",
distance: 15,
period: 5.4,
color: 0x4444ff,
size: 2.8
},
gliese581c: {
name: "格利波581c",
type: "超级地球",
diameter: "18,000 km",
distance: 25,
period: 12.9,
color: 0x55aa88,
size: 1.9
},
gliese581d: {
name: "格利波581d",
type: "超级地球",
diameter: "22,000 km",
distance: 40,
period: 66.6,
color: 0x66bb99,
size: 2.2
}
}
},
trappist: {
name: "和平星",
type: "红矇星",
mass: "0.08 M☂",
diameter: "0.12 D☂",
temperature: "2,550 K",
luminosity: "0.0005 L☂",
distance: 40,
position: { x: 1200, y: 800, z: 1000 },
color: 0xff5533,
glowColor: 0xff4400,
size: 4,
glowSize: 1.6,
planets: {
trappist1b: {
name: "和平星b",
type: "岩石行星",
diameter: "11,000 km",
distance: 15,
period: 1.5,
color: 0xaa6644,
size: 1.2
},
trappist1c: {
name: "和平星c",
type: "岩石行星",
diameter: "12,000 km",
distance: 22,
period: 2.4,
color: 0xbb7755,
size: 1.3
},
trappist1d: {
name: "和平星d",
type: "岩石行星",
diameter: "9,000 km",
distance: 30,
period: 4.0,
color: 0xcc8866,
size: 1.0
}
}
},
kepler22: {
name: "开普勒22",
type: "G型主序星",
mass: "0.97 M☂",
diameter: "0.98 D☂",
temperature: "5,518 K",
luminosity: "0.79 L☂",
distance: 600,
position: { x: -1500, y: 1000, z: 800 },
color: 0xffdd99,
glowColor: 0xffcc66,
size: 9,
glowSize: 2.4,
planets: {
kepler22b: {
name: "开普勒22b",
type: "超级地球",
diameter: "24,000 km",
distance: 45,
period: 290,
color: 0x44aa88,
size: 2.2
}
}
},
gliese667: {
name: "格利波667",
type: "红矇星",
mass: "0.33 M☂",
diameter: "0.42 D☂",
temperature: "3,700 K",
luminosity: "0.013 L☂",
distance: 22.7,
position: { x: -1700, y: -1200, z: 900 },
color: 0xff6633,
glowColor: 0xff5500,
size: 5,
glowSize: 1.9,
planets: {
gliese667cb: {
name: "格利波667Cb",
type: "超级地球",
diameter: "18,000 km",
distance: 18,
period: 28,
color: 0xbb8866,
size: 1.9
},
gliese667Cc: {
name: "格利波667Cc",
type: "超级地球",
diameter: "20,000 km",
distance: 25,
period: 39,
color: 0xcc9977,
size: 2.1
}
}
},
hd40307: {
name: "HD 40307",
type: "K型主序星",
mass: "0.77 M☂",
diameter: "0.72 D☂",
temperature: "4,977 K",
luminosity: "0.23 L☂",
distance: 42.4,
position: { x: 1600, y: 1100, z: -1300 },
color: 0xffcc66,
glowColor: 0xffbb55,
size: 8,
glowSize: 2.4,
planets: {
hd40307b: {
name: "HD 40307b",
type: "超级地球",
diameter: "16,000 km",
distance: 12,
period: 4.3,
color: 0xaa8855,
size: 1.8
},
hd40307c: {
name: "HD 40307c",
type: "超级地球",
diameter: "17,000 km",
distance: 20,
period: 9.6,
color: 0xbb9966,
size: 1.9
},
hd40307d: {
name: "HD 40307d",
type: "超级地球",
diameter: "19,000 km",
distance: 30,
period: 20.5,
color: 0xccaa77,
size: 2.0
}
}
},
kepler186: {
name: "开普勒186",
type: "红矇星",
mass: "0.48 M☂",
diameter: "0.47 D☂",
temperature: "3,788 K",
luminosity: "0.041 L☂",
distance: 500,
position: { x: -2000, y: 1500, z: 1800 },
color: 0xff5533,
glowColor: 0xff4400,
size: 6,
glowSize: 2.0,
planets: {
kepler186f: {
name: "开普勒186f",
type: "岩石行星",
diameter: "13,000 km",
distance: 35,
period: 130,
color: 0x44aa88,
size: 1.5
}
}
},
kepler452: {
name: "开普勒452",
type: "G型主序星",
mass: "1.04 M☂",
diameter: "1.11 D☂",
temperature: "5,757 K",
luminosity: "1.2 L☂",
distance: 1400,
position: { x: 2200, y: -1800, z: 1600 },
color: 0xffdd99,
glowColor: 0xffcc66,
size: 10,
glowSize: 2.8,
planets: {
kepler452b: {
name: "开普勒452b",
type: "超级地球",
diameter: "18,000 km",
distance: 50,
period: 385,
color: 0x55bb99,
size: 1.9
}
}
},
kepler62: {
name: "开普勒62",
type: "K型主序星",
mass: "0.69 M☂",
diameter: "0.64 D☂",
temperature: "4,925 K",
luminosity: "0.21 L☂",
distance: 990,
position: { x: -1800, y: -2200, z: 1200 },
color: 0xffbb66,
glowColor: 0xffaa44,
size: 7,
glowSize: 2.2,
planets: {
kepler62e: {
name: "开普勒62e",
type: "超级地球",
diameter: "17,000 km",
distance: 40,
period: 122,
color: 0x66aa88,
size: 1.8
},
kepler62f: {
name: "开普勒62f",
type: "超级地球",
diameter: "16,000 km",
distance: 55,
period: 267,
color: 0x77bb99,
size: 1.7
}
}
},
vega: {
name: "织女星",
type: "A型主序星",
mass: "2.1 M☂",
diameter: "2.3 D☂",
temperature: "9,600 K",
luminosity: "40 L☂",
distance: 25,
position: { x: 2500, y: 1200, z: -800 },
color: 0xbbeeff,
glowColor: 0x88ccff,
size: 15,
glowSize: 3.2
},
arcturus: {
name: "大角星",
type: "K型巨星",
mass: "1.1 M☂",
diameter: "25 D☂",
temperature: "4,300 K",
luminosity: "170 L☂",
distance: 37,
position: { x: -2200, y: 1800, z: 1500 },
color: 0xffaa66,
glowColor: 0xff8844,
size: 20,
glowSize: 4.0
},
altair: {
name: "牛郎星",
type: "A型主序星",
mass: "1.8 M☂",
diameter: "1.8 D☂",
temperature: "7,700 K",
luminosity: "11 L☂",
distance: 17,
position: { x: 1800, y: -1600, z: 900 },
color: 0xeeeeff,
glowColor: 0xccddff,
size: 13,
glowSize: 2.8
},
betelgeuse: {
name: "参宿四",
type: "M型超巨星",
mass: "11 M☂",
diameter: "1,000 D☂",
temperature: "3,500 K",
luminosity: "126,000 L☂",
distance: 640,
position: { x: -3000, y: 2500, z: 2000 },
color: 0xff4422,
glowColor: 0xff2200,
size: 30,
glowSize: 6.0
},
rigel: {
name: "参宿七",
type: "B型超巨星",
mass: "21 M☂",
diameter: "78 D☂",
temperature: "12,100 K",
luminosity: "120,000 L☂",
distance: 860,
position: { x: 2800, y: -2200, z: 1800 },
color: 0xbbeeff,
glowColor: 0x88ccff,
size: 25,
glowSize: 5.0
},
// 新增的5个星系
pollux: {
name: "北河三",
type: "K型巨星",
mass: "1.9 M☂",
diameter: "8.8 D☂",
temperature: "4,666 K",
luminosity: "32 L☂",
distance: 33.7,
position: { x: 1000, y: 500, z: -800 },
color: 0xffaa66,
glowColor: 0xff8844,
size: 12,
glowSize: 2.5
},
procyon: {
name: "南河三",
type: "F型主序星",
mass: "1.5 M☂",
diameter: "2.0 D☂",
temperature: "6,530 K",
luminosity: "6.9 L☂",
distance: 11.4,
position: { x: -1200, y: 300, z: 600 },
color: 0xffffcc,
glowColor: 0xffff99,
size: 9,
glowSize: 2.2
},
aldebaran: {
name: "毕宿五",
type: "K型巨星",
mass: "1.2 M☂",
diameter: "44 D☂",
temperature: "3,910 K",
luminosity: "439 L☂",
distance: 65.3,
position: { x: 1500, y: -900, z: -1200 },
color: 0xff6633,
glowColor: 0xff5522,
size: 18,
glowSize: 3.5
},
spica: {
name: "角宿一",
type: "B型主序星",
mass: "11.4 M☂",
diameter: "7.4 D☂",
temperature: "22,400 K",
luminosity: "20,500 L☂",
distance: 250,
position: { x: -2000, y: 1800, z: -1500 },
color: 0xbbeeff,
glowColor: 0x88ccff,
size: 14,
glowSize: 3.0
},
antares: {
name: "心宿二",
type: "M型超巨星",
mass: "12 M☂",
diameter: "680 D☂",
temperature: "3,600 K",
luminosity: "75,900 L☂",
distance: 550,
position: { x: 2500, y: -2000, z: 1800 },
color: 0xff4422,
glowColor: 0xff2200,
size: 28,
glowSize: 5.5
}
};
// 初始化Three.js场景
function initThreeJS() {
try {
// 创建场景
scene = new THREE.Scene();
// 创建相机
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100000);
camera.position.set(0, 500, 1500);
// 创建渲染器
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById('canvas'),
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
// 添加轨道控制
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 50;
controls.maxDistance = 10000;
// 创建星空背景
createStarBackground();
// 创建恒星系统
createStarSystems();
// 添加环境光
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
// 监听窗口大小变化
window.addEventListener('resize', onWindowResize);
// 监听键盘事件
window.addEventListener('keydown', onKeyDown);
return true;
} catch (error) {
console.error("初始化Three.js失败:", error);
document.getElementById('loading').innerHTML = "<div style='color: #ff6666;'>初始化失败: " + error.message + "</div>" +
"<div style='margin-top: 20px; font-size: 14px;'>请检查浏览器控制台获取更多信息</div>";
return false;
}
}
// 创建星空背景
function createStarBackground() {
const starGeometry = new THREE.BufferGeometry();
const starCount = 5000;
const positionArray = new Float32Array(starCount * 3);
const colorArray = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
const radius = 3000 + Math.random() * 5000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
positionArray[i3] = radius * Math.sin(phi) * Math.cos(theta);
positionArray[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positionArray[i3 + 2] = radius * Math.cos(phi);
const colorVal = 0.7 + Math.random() * 0.3;
colorArray[i3] = colorVal;
colorArray[i3 + 1] = colorVal;
colorArray[i3 + 2] = colorVal + Math.random() * 0.2;
}
starGeometry.setAttribute('position', new THREE.BufferAttribute(positionArray, 3));
starGeometry.setAttribute('color', new THREE.BufferAttribute(colorArray, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.8,
sizeAttenuation: true,
vertexColors: true
});
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// 创建恒星系统
function createStarSystems() {
Object.keys(starData).forEach(function(key) {
const data = starData[key];
// 创建恒星
createStar(key, data);
// 创建行星
if (data.planets) {
Object.keys(data.planets).forEach(function(planetKey) {
createPlanet(key, planetKey, data.planets[planetKey]);
});
}
// 创建小行星带
if (data.asteroidBelt) {
createAsteroidBelt(key, data.asteroidBelt);
}
// 创建距离标签
createDistanceLabel(key, data);
});
}
// 创建恒星
function createStar(key, data) {
// 创建恒星几何体
const geometry = new THREE.SphereGeometry(data.size * config.objectSize, 32, 32);
const material = new THREE.MeshPhongMaterial({
color: data.color,
emissive: data.color,
emissiveIntensity: 0.6,
shininess: 100
});
// 创建恒星网格
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(data.position.x, data.position.y, data.position.z);
mesh.userData = { type: 'star', id: key };
scene.add(mesh);
// 存储引用
starMeshes[key] = mesh;
// 创建光晕效果 - 类似参考代码中的太阳光晕
createAdvancedStarGlow(mesh, data);
// 创建轨道
createOrbit(key, data);
// 创建标签
createLabel(key, data);
// 为恒星添加点光源
const light = new THREE.PointLight(data.glowColor || data.color, 1, 1000);
light.position.set(data.position.x, data.position.y, data.position.z);
scene.add(light);
}
// 创建高级恒星光晕效果(类似参考代码中的太阳光晕)
function createAdvancedStarGlow(starMesh, data) {
// 创建多层光晕效果
const glowLayers = [
{ size: 1.5, opacity: 0.6, color: data.glowColor || data.color },
{ size: 2.0, opacity: 0.4, color: data.glowColor || data.color },
{ size: 2.5, opacity: 0.2, color: data.glowColor || data.color }
];
glowLayers.forEach(layer => {
const glowMaterial = new THREE.MeshBasicMaterial({
color: layer.color,
transparent: true,
opacity: layer.opacity,
blending: THREE.AdditiveBlending
});
const glowGeometry = new THREE.SphereGeometry(
data.size * config.objectSize * layer.size,
32,
32
);
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
glow.position.set(0, 0, 0);
glow.userData = { type: 'glow' };
starMesh.add(glow);
});
// 添加粒子光晕效果
createParticleGlow(starMesh, data);
}
// 创建粒子光晕效果
function createParticleGlow(starMesh, data) {
const particleCount = 100;
const particles = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const color = new THREE.Color(data.glowColor || data.color);
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// 随机位置(球体表面)
const radius = data.size * config.objectSize * (1.5 + Math.random() * 1.5);
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos((Math.random() * 2) - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// 随机颜色变化
colors[i3] = color.r + (Math.random() * 0.2 - 0.1);
colors[i3 + 1] = color.g + (Math.random() * 0.2 - 0.1);
colors[i3 + 2] = color.b + (Math.random() * 0.2 - 0.1);
}
particles.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particles.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
sizeAttenuation: true,
vertexColors: true,
transparent: true,
opacity: 0.6,
blending: THREE.AdditiveBlending
});
const particleSystem = new THREE.Points(particles, particleMaterial);
starMesh.add(particleSystem);
}
// 创建行星
function createPlanet(starKey, planetKey, data) {
const currentStarData = starData[starKey];
// 创建行星几何体
const geometry = new THREE.SphereGeometry(data.size, 24, 24);
const material = new THREE.MeshPhongMaterial({
color: data.color,
shininess: 30
});
// 创建行星网格
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(
currentStarData.position.x + data.distance,
currentStarData.position.y,
currentStarData.position.z
);
mesh.userData = { type: 'planet', id: planetKey, star: starKey };
scene.add(mesh);
// 存储引用
planets[starKey + '_' + planetKey] = mesh;
// 创建行星轨道
createPlanetOrbit(starKey, planetKey, data);
// 如果有行星环,创建环
if (data.rings) {
const ringGeometry = new THREE.RingGeometry(data.rings.innerRadius, data.rings.outerRadius, 32);
const ringMaterial = new THREE.MeshBasicMaterial({
color: data.rings.color,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.7
});
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.rotation.x = Math.PI / 2;
mesh.add(ring);
}
}
// 创建小行星带
function createAsteroidBelt(starKey, data) {
const currentStarData = starData[starKey];
const asteroidGroup = new THREE.Group();
asteroidGroup.position.set(currentStarData.position.x, currentStarData.position.y, currentStarData.position.z);
scene.add(asteroidGroup);
// 创建少量小行星
for (let i = 0; i < data.count/4; i++) {
const angle = Math.random() * Math.PI * 2;
const distance = data.innerRadius + Math.random() * (data.outerRadius - data.innerRadius);
const height = (Math.random() - 0.5) * 5;
const size = 0.2 + Math.random() * 0.8;
const geometry = new THREE.SphereGeometry(size, 8, 8);
const material = new THREE.MeshPhongMaterial({
color: data.color,
shininess: 10
});
const asteroid = new THREE.Mesh(geometry, material);
asteroid.position.set(
Math.cos(angle) * distance,
height,
Math.sin(angle) * distance
);
asteroidGroup.add(asteroid);
}
// 存储引用
asteroidBelts[starKey] = asteroidGroup;
}
// 创建轨道
function createOrbit(key, data) {
// 计算轨道半径
const radius = Math.sqrt(
data.position.x * data.position.x +
data.position.y * data.position.y +
data.position.z * data.position.z
);
if (radius > 0) {
// 创建轨道几何体
const orbitGeometry = new THREE.RingGeometry(radius - 0.5, radius + 0.5, 64);
const orbitMaterial = new THREE.MeshBasicMaterial({
color: 0x3366cc,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.2
});
// 创建轨道网格
const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial);
orbit.rotation.x = Math.PI / 2;
scene.add(orbit);
// 存储引用
orbits[key] = orbit;
}
}
// 创建行星轨道
function createPlanetOrbit(starKey, planetKey, data) {
const currentStarData = starData[starKey];
// 创建轨道几何体
const orbitGeometry = new THREE.RingGeometry(data.distance - 0.2, data.distance + 0.2, 64);
const orbitMaterial = new THREE.MeshBasicMaterial({
color: 0x4488ff,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.1
});
// 创建轨道网格
const orbit = new THREE.Mesh(orbitGeometry, orbitMaterial);
orbit.rotation.x = Math.PI / 2;
orbit.position.set(currentStarData.position.x, currentStarData.position.y, currentStarData.position.z);
scene.add(orbit);
// 存储引用
orbits[starKey + '_' + planetKey] = orbit;
}
// 创建标签
function createLabel(key, data) {
// 创建画布
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = 200;
canvas.height = 50;
// 绘制标签背景
context.fillStyle = 'rgba(0, 20, 40, 0.8)';
context.fillRect(0, 0, canvas.width, canvas.height);
// 解码HTML实体
const decodedName = decodeHTML(data.name);
// 绘制文字
context.font = 'bold 20px Arial, Microsoft YaHei, sans-serif';
context.fillStyle = '#aaffff';
context.textAlign = 'center';
context.fillText(decodedName, canvas.width / 2, canvas.height / 2 + 6);
// 创建纹理
const texture = new THREE.CanvasTexture(canvas);
// 创建精灵材质
const material = new THREE.SpriteMaterial({
map: texture,
transparent: true
});
// 创建精灵
const sprite = new THREE.Sprite(material);
sprite.position.set(
data.position.x,
data.position.y + data.size * config.objectSize + 5,
data.position.z
);
sprite.scale.set(16, 4, 1);
sprite.userData = { type: 'label', id: key };
scene.add(sprite);
// 存储引用
labels[key] = sprite;
}
// 创建距离标签
function createDistanceLabel(key, data) {
// 创建画布
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = 120;
canvas.height = 30;
// 绘制标签背景
context.fillStyle = 'rgba(0, 20, 40, 0.6)';
context.fillRect(0, 0, canvas.width, canvas.height);
// 绘制文字
context.font = '14px Arial, Microsoft YaHei, sans-serif';
context.fillStyle = '#88ddff';
context.textAlign = 'center';
context.fillText(data.distance + ' 光年', canvas.width / 2, canvas.height / 2 + 4);
// 创建纹理
const texture = new THREE.CanvasTexture(canvas);
// 创建精灵材质
const material = new THREE.SpriteMaterial({
map: texture,
transparent: true
});
// 创建精灵
const sprite = new THREE.Sprite(material);
sprite.position.set(
data.position.x,
data.position.y - data.size * config.objectSize - 8,
data.position.z
);
sprite.scale.set(12, 3, 1);
sprite.userData = { type: 'distanceLabel', id: key };
sprite.visible = config.showDistanceLabels;
scene.add(sprite);
// 存储引用
distanceLabels[key] = sprite;
}
// 动画循环
function animate() {
requestAnimationFrame(animate);
// 更新控制
controls.update();
// 旋转恒星和行星
Object.keys(starMeshes).forEach(function(key) {
starMeshes[key].rotation.y += 0.001 * config.simulationSpeed;
});
Object.keys(planets).forEach(function(key) {
const parts = key.split('_');
const starKey = parts[0];
const planetKey = parts[1];
const currentStarData = starData[starKey];
const planetData = currentStarData.planets[planetKey];
// 更新行星位置(绕恒星公转)
const time = Date.now() * 0.001 * config.simulationSpeed;
const angle = (time / planetData.period) * Math.PI * 2;
planets[key].position.set(
currentStarData.position.x + Math.cos(angle) * planetData.distance,
currentStarData.position.y,
currentStarData.position.z + Math.sin(angle) * planetData.distance
);
// 行星自转
planets[key].rotation.y += 0.02 * config.simulationSpeed;
});
// 旋转小行星带
Object.keys(asteroidBelts).forEach(function(key) {
asteroidBelts[key].rotation.y += 0.0005 * config.simulationSpeed;
});
// 隐藏加载界面
if (!loadingComplete) {
loadingComplete = true;
document.getElementById('loading').style.display = 'none';
}
// 渲染场景
renderer.render(scene, camera);
}
// 窗口大小变化处理
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 键盘事件处理
function onKeyDown(event) {
const moveSpeed = 50;
switch(event.key) {
case 'w':
case 'W':
camera.position.z -= moveSpeed;
break;
case 's':
case 'S':
camera.position.z += moveSpeed;
break;
case 'a':
case 'A':
camera.position.x -= moveSpeed;
break;
case 'd':
case 'D':
camera.position.x += moveSpeed;
break;
case 'q':
case 'Q':
camera.position.y -= moveSpeed;
break;
case 'e':
case 'E':
camera.position.y += moveSpeed;
break;
}
}
// 更新天体信息显示
function updateObjectInfo(key, type) {
let data, infoHtml;
if (type === 'star') {
data = starData[key];
const decodedName = decodeHTML(data.name);
const decodedType = decodeHTML(data.type);
const decodedMass = decodeHTML(data.mass);
const decodedDiameter = decodeHTML(data.diameter);
const decodedTemperature = decodeHTML(data.temperature);
const decodedLuminosity = decodeHTML(data.luminosity);
infoHtml = `
<strong>类型:</strong> ${decodedType}<br>
<strong>质量:</strong> ${decodedMass}<br>
<strong>直径:</strong> ${decodedDiameter}<br>
<strong>温度:</strong> ${decodedTemperature}<br>
<strong>光度:</strong> ${decodedLuminosity}<br>
<strong>距离:</strong> ${data.distance} 光年<br>
<strong>位置:</strong> ${Math.round(data.position.x)}, ${Math.round(data.position.y)}, ${Math.round(data.position.z)}
`;
// 添加行星列表
if (data.planets) {
infoHtml += `<div class="star-info"><strong>行星系统:</strong><div class="planet-list">`;
Object.keys(data.planets).forEach(function(planetKey) {
const planetName = decodeHTML(data.planets[planetKey].name);
infoHtml += `<div class="planet-item" data-star="${key}" data-planet="${planetKey}">${planetName}</div>`;
});
infoHtml += `</div></div>`;
}
document.getElementById('selected-object').textContent = decodedName;
} else if (type === 'planet') {
const parts = key.split('_');
const starKey = parts[0];
const planetKey = parts[1];
data = starData[starKey].planets[planetKey];
const starName = decodeHTML(starData[starKey].name);
const planetName = decodeHTML(data.name);
const planetType = decodeHTML(data.type);
const planetDiameter = decodeHTML(data.diameter);
infoHtml = `
<strong>类型:</strong> ${planetType}<br>
<strong>直径:</strong> ${planetDiameter}<br>
<strong>轨道半径:</strong> ${data.distance} 单位<br>
<strong>公转周期:</strong> ${data.period} 天<br>
<strong>所属恒星:</strong> ${starName}
`;
document.getElementById('selected-object').textContent = planetName;
}
document.getElementById('object-info').innerHTML = infoHtml;
// 添加行星点击事件
document.querySelectorAll('.planet-item').forEach(function(item) {
item.addEventListener('click', function() {
const starKey = item.getAttribute('data-star');
const planetKey = item.getAttribute('data-planet');
focusOnPlanet(starKey, planetKey);
});
});
}
// 聚焦到行星
function focusOnPlanet(starKey, planetKey) {
const currentStarData = starData[starKey];
const planetData = currentStarData.planets[planetKey];
controls.target.set(
currentStarData.position.x + planetData.distance,
currentStarData.position.y,
currentStarData.position.z
);
camera.position.set(
currentStarData.position.x + planetData.distance,
currentStarData.position.y,
currentStarData.position.z + 15
);
updateObjectInfo(starKey + '_' + planetKey, 'planet');
}
// 设置事件监听器
function setupEventListeners() {
// 缩放控制
document.getElementById('zoom').addEventListener('input', function(e) {
config.zoomLevel = parseFloat(e.target.value);
document.getElementById('zoom-value').textContent = config.zoomLevel.toFixed(1);
camera.zoom = config.zoomLevel;
camera.updateProjectionMatrix();
});
// 速度控制
document.getElementById('speed').addEventListener('input', function(e) {
config.simulationSpeed = parseFloat(e.target.value);
document.getElementById('speed-value').textContent = config.simulationSpeed.toFixed(1);
});
// 大小控制
document.getElementById('size').addEventListener('input', function(e) {
config.objectSize = parseFloat(e.target.value);
document.getElementById('size-value').textContent = config.objectSize.toFixed(1);
// 更新所有天体大小
Object.keys(starMeshes).forEach(function(key) {
const data = starData[key];
starMeshes[key].scale.setScalar(config.objectSize);
// 更新标签位置
if (labels[key]) {
labels[key].position.set(
data.position.x,
data.position.y + data.size * config.objectSize + 5,
data.position.z
);
}
// 更新距离标签位置
if (distanceLabels[key]) {
distanceLabels[key].position.set(
data.position.x,
data.position.y - data.size * config.objectSize - 8,
data.position.z
);
}
});
});
// 切换名称显示
document.getElementById('toggle-names').addEventListener('click', function() {
config.showNames = !config.showNames;
Object.keys(labels).forEach(function(key) {
labels[key].visible = config.showNames;
});
this.innerHTML = config.showNames ? '隐藏名称' : '显示名称';
});
// 切换轨道显示
document.getElementById('toggle-orbits').addEventListener('click', function() {
config.showOrbits = !config.showOrbits;
Object.keys(orbits).forEach(function(key) {
orbits[key].visible = config.showOrbits;
});
this.innerHTML = config.showOrbits ? '隐藏轨道' : '显示轨道';
});
// 切换距离标签显示
document.getElementById('toggle-labels').addEventListener('click', function() {
config.showDistanceLabels = !config.showDistanceLabels;
Object.keys(distanceLabels).forEach(function(key) {
distanceLabels[key].visible = config.showDistanceLabels;
});
this.innerHTML = config.showDistanceLabels ? '隐藏距离' : '显示距离';
});
// 切换小行星带显示
document.getElementById('toggle-asteroids').addEventListener('click', function() {
config.showAsteroids = !config.showAsteroids;
Object.keys(asteroidBelts).forEach(function(key) {
asteroidBelts[key].visible = config.showAsteroids;
});
this.innerHTML = config.showAsteroids ? '隐藏小行星' : '显示小行星';
});
// 重置视图
document.getElementById('reset-view').addEventListener('click', function() {
controls.reset();
camera.position.set(0, 500, 1500);
config.zoomLevel = 1.0;
document.getElementById('zoom').value = config.zoomLevel;
document.getElementById('zoom-value').textContent = config.zoomLevel.toFixed(1);
camera.zoom = config.zoomLevel;
camera.updateProjectionMatrix();
// 修复:使用解码后的文本而不是HTML实体
document.getElementById('selected-object').textContent = decodeHTML(DEFAULT_SELECTED_OBJECT_TEXT);
document.getElementById('object-info').textContent = decodeHTML(DEFAULT_OBJECT_INFO_TEXT);
});
// 为所有恒星系统按钮添加点击事件
document.querySelectorAll('.star-system-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
const starKey = this.getAttribute('data-star');
focusOnStar(starKey);
});
});
// 搜索功能
document.getElementById('search-system').addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
document.querySelectorAll('.star-system-btn').forEach(function(btn) {
const btnText = decodeHTML(btn.textContent).toLowerCase();
if (btnText.includes(searchTerm)) {
btn.style.display = 'block';
} else {
btn.style.display = 'none';
}
});
});
// 分类标签
document.querySelectorAll('.tab-btn').forEach(function(tab) {
tab.addEventListener('click', function() {
// 移除所有active类
document.querySelectorAll('.tab-btn').forEach(function(t) {
t.classList.remove('active');
});
// 添加active类到当前标签
this.classList.add('active');
const category = this.getAttribute('data-category');
// 根据分类显示/隐藏恒星系统
document.querySelectorAll('.star-system-btn').forEach(function(btn) {
const starKey = btn.getAttribute('data-star');
const star = starData[starKey];
if (category === 'all') {
btn.style.display = 'block';
} else if (category === 'nearby' && star.distance <= 20) {
btn.style.display = 'block';
} else if (category === 'habitable' && star.planets) {
btn.style.display = 'block';
} else {
btn.style.display = 'none';
}
});
});
});
// 点击选择天体
renderer.domElement.addEventListener('click', function(event) {
const mouse = new THREE.Vector2();
const rect = renderer.domElement.getBoundingClientRect();
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
const object = intersects[0].object;
if (object.userData) {
if (object.userData.type === 'star') {
updateObjectInfo(object.userData.id, 'star');
} else if (object.userData.type === 'planet') {
updateObjectInfo(object.userData.star + '_' + object.userData.id, 'planet');
}
}
}
});
// 双击聚焦天体
renderer.domElement.addEventListener('dblclick', function(event) {
const mouse = new THREE.Vector2();
const rect = renderer.domElement.getBoundingClientRect();
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
const object = intersects[0].object;
if (object.userData) {
if (object.userData.type === 'star') {
focusOnStar(object.userData.id);
} else if (object.userData.type === 'planet') {
focusOnPlanet(object.userData.star, object.userData.id);
}
}
}
});
// 控制面板折叠功能
document.querySelector('.toggle-controls').addEventListener('click', function() {
const controls = document.getElementById('controls');
controls.classList.toggle('collapsed');
if (controls.classList.contains('collapsed')) {
this.innerHTML = '▶';
this.title = "展开控制板";
} else {
this.innerHTML = '▼';
this.title = "折叠控制板";
}
});
}
// 聚焦到恒星
function focusOnStar(starKey) {
const data = starData[starKey];
controls.target.set(data.position.x, data.position.y, data.position.z);
camera.position.set(
data.position.x,
data.position.y,
data.position.z + 30
);
updateObjectInfo(starKey, 'star');
}
// 模拟加载进度
function simulateLoading() {
let progress = 0;
const interval = setInterval(function() {
progress += Math.random() * 10;
if (progress >= 100) {
progress = 100;
clearInterval(interval);
// 初始化Three.js
if (initThreeJS()) {
// 设置事件监听器
setupEventListeners();
// 开始动画
animate();
}
}
// 确保进度条元素存在
const progressBar = document.getElementById('progress');
if (progressBar) {
progressBar.style.width = progress + '%';
}
}, 100);
}
// 启动应用
window.addEventListener('load', function() {
// 模拟加载进度
simulateLoading();
});
</script>
</body>
</html>
index.html
index.html