一、项目效果与核心亮点

先给大家直观展示项目效果:

  • 全屏黑色深空背景,搭配彩色渐变星云,氛围感拉满
  • 1000 颗随机大小、随机闪烁的星星,布满整个屏幕
  • 50 个彩色星系,随机旋转、发光,层次丰富
  • 中心蓝色行星 + 光环,3 颗卫星按不同速度、方向公转
  • 随机位置划过的流星,动态感拉满
  • 环绕行星的小行星带,持续旋转
  • 纯前端实现,无图片、无第三方库,加载极快

核心技术点:

  1. CSS @keyframes 实现流畅动画
  2. 径向渐变 / 线性渐变打造星球、星云、流星质感
  3. transform 实现 3D 旋转、公转、缩放效果
  4. JS 动态生成大量元素,随机化属性更自然
  5. 绝对定位 + 层级管理,构建深空立体空间

二、项目完整代码(带详细注释)

1. HTML 结构(搭建宇宙骨架)

HTML 只负责搭建容器,所有视觉元素由 CSS 绘制、JS 动态生成,结构极简清晰。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>

  <title>Cosmic Canvas 深空艺术</title>

  <link rel="stylesheet" href="style.css" />

</head>

<body>

  <!-- 宇宙总容器 -->

  <div class="space-scene">

    <!-- 星星容器 -->

    <div class="stars"></div>

    <!-- 星系容器 -->

    <div class="galaxies"></div>

    <!-- 流星容器 -->

    <div class="shooting-stars"></div>

    <!-- 星云容器 -->

    <div class="nebula"></div>

    <!-- 行星系统:主行星+光环+卫星 -->

    <div class="planet-system">

      <div class="planet main-planet"></div>

      <div class="planet-ring"></div>

      <div class="moon moon1"></div>

      <div class="moon moon2"></div>

      <div class="moon moon3"></div>

    </div>

    <!-- 小行星带容器 -->

    <div class="asteroid-belt"></div>

  </div>

  <script src="script.js"></script>

</body>

</html>

2. CSS 样式(绘制宇宙万物)

CSS 是这个项目的核心,负责所有视觉效果、动画、质感的实现,每一行都加了注释,方便理解。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

/* 全局初始化:清除默认边距,全屏展示,隐藏滚动条 */

body,

html {

  margin: 0;

  padding: 0;

  height: 100%;

  /* 隐藏溢出内容,保证星空全屏 */

  overflow: hidden;

}

/* 宇宙场景容器:全屏黑色背景,相对定位作为子元素参照物 */

.space-scene {

  width: 100%;

  height: 100%;

  background: #000000;

  position: relative;

  overflow: hidden;

}

/* 星星+星系公共样式:绝对定位铺满全屏 */

.stars,

.galaxies {

  position: absolute;

  top: 0;

  left: 0;

  width: 100%;

  height: 100%;

}

/* 单个星星样式:白色圆点,闪烁动画 */

.star {

  position: absolute;

  background-color: #fff;

  border-radius: 50%;

  /* 闪烁动画:4s无限循环,缓动效果 */

  animation: twinkle 4s infinite ease-in-out;

}

/* 单个星系样式:椭圆形状,发光动画 */

.galaxy {

  position: absolute;

  border-radius: 50%;

  /* 发光动画:4s无限交替循环 */

  animation: glow 4s infinite alternate;

}

/* 星星闪烁动画:透明度+缩放交替 */

@keyframes twinkle {

  0%,

  100% {

    opacity: 0.5;

    transform: scale(1);

  }

  50% {

    opacity: 1;

    transform: scale(1.2);

  }

}

/* 星系发光动画:阴影渐变,营造光晕 */

@keyframes glow {

  0% {

    box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.1);

  }

  100% {

    box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.3);

  }

}

/* 星云效果:多层径向渐变+模糊+透明度,梦幻氛围 */

.nebula {

  position: absolute;

  top: 0;

  left: 0;

  right: 0;

  bottom: 0;

  /* 多层彩色径向渐变,叠加出星云色彩 */

  background: radial-gradient(

      circle at 20% 80%,

      rgba(255, 0, 100, 0.1) 0%,

      transparent 50%

    ),

    radial-gradient(

      circle at 80% 20%,

      rgba(0, 100, 255, 0.1) 0%,

      transparent 50%

    ),

    radial-gradient(

      circle at 40% 40%,

      rgba(255, 100, 0, 0.1) 0%,

      transparent 60%

    ),

    radial-gradient(

      circle at 60% 60%,

      rgba(100, 0, 255, 0.1) 0%,

      transparent 60%

    );

  /* 模糊处理,柔化边缘 */

  filter: blur(20px);

  opacity: 0.5;

}

/* 行星系统容器:居中定位,作为行星和卫星的父容器 */

.planet-system {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

  width: 300px;

  height: 300px;

}

/* 主行星:蓝色渐变,圆形,发光阴影,居中 */

.main-planet {

  width: 150px;

  height: 150px;

  /* 径向渐变打造星球立体感 */

  background: radial-gradient(circle at 30% 30%, #4a89dc, #1c3c78);

  border-radius: 50%;

  /* 外发光,模拟星球光晕 */

  box-shadow: 0 0 50px rgba(74, 137, 220, 0.8);

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

}

/* 行星光环:3D旋转,半透明边框,模拟土星环效果 */

.planet-ring {

  width: 225px;

  height: 225px;

  border: 10px solid rgba(255, 255, 255, 0.2);

  border-radius: 50%;

  position: absolute;

  top: 50%;

  left: 50%;

  /* X轴旋转75度,呈现3D环装效果 */

  transform: translate(-50%, -50%) rotateX(75deg);

}

/* 卫星公共样式:圆形,居中定位 */

.moon {

  width: 20px;

  height: 20px;

  border-radius: 50%;

  position: absolute;

  top: 50%;

  left: 50%;

}

/* 卫星1:金色,30s公转 */

.moon1 {

  animation: orbit 30s linear infinite;

  background: radial-gradient(circle at 30% 30%, #ffd700, #ffa500);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(255, 215, 0, 0.6);

}

/* 卫星2:蓝色,反向45s公转 */

.moon2 {

  animation: orbit 45s linear infinite reverse;

  background: radial-gradient(circle at 30% 30%, #add8e6, #4169e1);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(65, 105, 225, 0.6);

}

/* 卫星3:黄色,60s公转 */

.moon3 {

  animation: orbit 60s linear infinite;

  background: radial-gradient(circle at 30% 30%, #f0e68c, #daa520);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(218, 165, 32, 0.6);

}

/* 卫星公转动画:核心!rotate+translate组合实现圆周运动 */

@keyframes orbit {

  0% {

    transform: rotate(0deg) translateX(100px) rotate(0deg);

  }

  100% {

    transform: rotate(360deg) translateX(100px) rotate(-360deg);

  }

}

/* 流星容器:全屏铺满 */

.shooting-stars {

  position: absolute;

  top: 0;

  left: 0;

  width: 100%;

  height: 100%;

}

/* 流星样式:线性渐变,从白到透明,模拟流星尾迹 */

.shooting-star {

  position: absolute;

  height: 2px;

  background: linear-gradient(90deg, #ffffff, transparent);

  /* 流星划过动画 */

  animation: shoot 3s ease-out infinite;

}

/* 流星划过动画:斜向移动+透明度消失 */

@keyframes shoot {

  0% {

    transform: translateX(-100px) translateY(100px);

    opacity: 1;

  }

  70% {

    opacity: 1;

  }

  100% {

    transform: translateX(1000px) translateY(-1000px);

    opacity: 0;

  }

}

/* 小行星带:3D旋转,环形布局 */

.asteroid-belt {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%) rotateX(75deg);

  width: 350px;

  height: 350px;

  border-radius: 50%;

}

/* 小行星样式:灰色小圆点,环形旋转 */

.asteroid {

  position: absolute;

  background: #555;

  border-radius: 50%;

  top: 50%;

  left: 50%;

  /* 旋转中心设置为环的边缘 */

  transform-origin: 175px 0;

  animation: rotate 20s linear infinite;

}

/* 小行星旋转动画:沿环公转 */

@keyframes rotate {

  0% {

    transform: rotate(0deg) translateX(175px) rotate(0deg);

  }

  100% {

    transform: rotate(360deg) translateX(175px) rotate(-360deg);

  }

}

3. JavaScript(动态生成宇宙元素)

JS 负责批量生成星星、星系、流星、小行星,随机化大小、位置、动画时长,让星空更自然不呆板。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

/**

 * 动态创建天体元素:星星、星系、流星、小行星

 * 批量生成+随机属性,提升效率与真实感

 */

function createCelestialObjects() {

  // 获取所有容器DOM

  const starsContainer = document.querySelector(".stars");

  const galaxiesContainer = document.querySelector(".galaxies");

  const shootingStarsContainer = document.querySelector(".shooting-stars");

  const asteroidBelt = document.querySelector(".asteroid-belt");

  // 配置元素数量,可自行调整

  const starCount = 1000; // 星星数量

  const galaxyCount = 50; // 星系数量

  const shootingStarCount = 5; // 同时存在的流星数量

  const asteroidCount = 100; // 小行星数量

  // 星系颜色库

  const galaxyColors = ["#FFD700""#87CEEB""#FFA500""#FF69B4""#00CED1"];

  // 1. 生成1000颗星星

  for (let i = 0; i < starCount; i++) {

    const star = document.createElement("div");

    star.className = "star";

    // 随机大小:0-2px

    star.style.width = star.style.height = `${Math.random() * 2}px`;

    // 随机位置:全屏百分比

    star.style.left = `${Math.random() * 100}%`;

    star.style.top = `${Math.random() * 100}%`;

    // 随机动画时长:2-4s

    star.style.animationDuration = `${Math.random() * 2 + 2}s`;

    // 随机动画延迟:0-4s

    star.style.animationDelay = `${Math.random() * 4}s`;

    starsContainer.appendChild(star);

  }

  // 2. 生成50个星系

  for (let i = 0; i < galaxyCount; i++) {

    const galaxy = document.createElement("div");

    galaxy.className = "galaxy";

    // 随机大小:5-25px

    const size = Math.random() * 20 + 5;

    galaxy.style.width = `${size}px`;

    galaxy.style.height = `${size / 2}px`;

    // 随机位置

    galaxy.style.left = `${Math.random() * 100}%`;

    galaxy.style.top = `${Math.random() * 100}%`;

    // 随机颜色

    galaxy.style.backgroundColor = galaxyColors[Math.floor(Math.random() * galaxyColors.length)];

    // 随机旋转角度

    galaxy.style.transform = `rotate(${Math.random() * 360}deg)`;

    galaxiesContainer.appendChild(galaxy);

  }

  // 3. 生成流星

  for (let i = 0; i < shootingStarCount; i++) {

    const shootingStar = document.createElement("div");

    shootingStar.className = "shooting-star";

    // 随机位置

    shootingStar.style.left = `${Math.random() * 100}%`;

    shootingStar.style.top = `${Math.random() * 100}%`;

    // 随机延迟,避免同时出现

    shootingStar.style.animationDelay = `${Math.random() * 5}s`;

    shootingStarsContainer.appendChild(shootingStar);

  }

  // 4. 生成小行星

  for (let i = 0; i < asteroidCount; i++) {

    const asteroid = document.createElement("div");

    asteroid.className = "asteroid";

    // 随机大小:1-4px

    asteroid.style.width = asteroid.style.height = `${Math.random() * 3 + 1}px`;

    // 随机动画时长:10-20s

    asteroid.style.animationDuration = `${Math.random() * 10 + 10}s`;

    asteroid.style.animationDelay = `${Math.random() * 10}s`;

    asteroidBelt.appendChild(asteroid);

  }

}

// 页面加载完成后执行,确保DOM就绪

window.addEventListener("load", createCelestialObjects);

三、核心技术解析

1. 公转动画实现原理

卫星和小行星的圆周运动是项目核心,用到 CSS transform 组合技巧:

1

transform: rotate(360deg) translateX(100px) rotate(-360deg);

  • 第一层 rotate:让元素绕父容器中心旋转
  • translateX:控制公转半径
  • 第二层反向 rotate:保证元素自身不旋转,只沿轨道公转

2. 3D 视觉效果

行星光环和小行星带使用 rotateX(75deg),把平面圆环压成倾斜的 3D 环,配合阴影和渐变,瞬间有太空立体感。

3. 性能优化要点

  • 用 JS 批量生成元素,避免手动写 1000 个 div
  • 动画使用 transform 和 opacity,触发合成线程,不回流重绘
  • 星星大小、动画延迟随机化,减少视觉重复
  • 无图片、无字体包,纯代码渲染,加载速度极快

四、项目拓展方向

大家可以基于这个项目继续优化,做出更炫酷的效果:

  1. 添加鼠标交互:星星跟随鼠标移动、点击生成流星
  2. 增加更多行星:多行星系统,不同轨道、颜色、转速
  3. 添加音效:深空白噪音,沉浸式体验拉满
  4. 适配移动端:调整尺寸,支持手机端全屏展示
  5. 加入暗黑模式切换、星空亮度调节

五、演示代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<div class="space-scene">

  <div class="stars"></div>

  <div class="galaxies"></div>

  <div class="shooting-stars"></div>

  <div class="nebula"></div>

  <div class="planet-system">

    <div class="planet main-planet"></div>

    <div class="planet-ring"></div>

    <div class="moon moon1"></div>

    <div class="moon moon2"></div>

    <div class="moon moon3"></div>

  </div>

  <div class="asteroid-belt"></div>

</div>

  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

body,

html {

  margin: 0;

  padding: 0;

  height: 100%;

  overflow: hidden;

}

.space-scene {

  width: 100%;

  height: 100%;

  background: #000000;

  position: relative;

  overflow: hidden;

}

.stars,

.galaxies {

  position: absolute;

  top: 0;

  left: 0;

  width: 100%;

  height: 100%;

}

.star {

  position: absolute;

  background-color: #fff;

  border-radius: 50%;

  animation: twinkle 4s infinite ease-in-out;

}

.galaxy {

  position: absolute;

  border-radius: 50%;

  animation: glow 4s infinite alternate;

}

@keyframes twinkle {

  0%,

  100% {

    opacity: 0.5;

    transform: scale(1);

  }

  50% {

    opacity: 1;

    transform: scale(1.2);

  }

}

@keyframes glow {

  0% {

    box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.1);

  }

  100% {

    box-shadow: 0 0 10px 2px rgba(255, 255, 255, 0.3);

  }

}

.nebula {

  position: absolute;

  top: 0;

  left: 0;

  right: 0;

  bottom: 0;

  background: radial-gradient(

      circle at 20% 80%,

      rgba(255, 0, 100, 0.1) 0%,

      transparent 50%

    ),

    radial-gradient(

      circle at 80% 20%,

      rgba(0, 100, 255, 0.1) 0%,

      transparent 50%

    ),

    radial-gradient(

      circle at 40% 40%,

      rgba(255, 100, 0, 0.1) 0%,

      transparent 60%

    ),

    radial-gradient(

      circle at 60% 60%,

      rgba(100, 0, 255, 0.1) 0%,

      transparent 60%

    );

  filter: blur(20px);

  opacity: 0.5;

}

.planet-system {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

  width: 300px;

  height: 300px;

}

.main-planet {

  width: 150px;

  height: 150px;

  background: radial-gradient(circle at 30% 30%, #4a89dc, #1c3c78);

  border-radius: 50%;

  box-shadow: 0 0 50px rgba(74, 137, 220, 0.8);

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

}

.planet-ring {

  width: 225px;

  height: 225px;

  border: 10px solid rgba(255, 255, 255, 0.2);

  border-radius: 50%;

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%) rotateX(75deg);

}

.moon {

  width: 20px;

  height: 20px;

  border-radius: 50%;

  position: absolute;

  top: 50%;

  left: 50%;

}

.moon1 {

  animation: orbit 30s linear infinite; /* Increased from 10s to 30s */

  background: radial-gradient(circle at 30% 30%, #ffd700, #ffa500);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(255, 215, 0, 0.6);

}

.moon2 {

  animation: orbit 45s linear infinite reverse; /* Increased from 15s to 45s */

  background: radial-gradient(circle at 30% 30%, #add8e6, #4169e1);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(65, 105, 225, 0.6);

}

.moon3 {

  animation: orbit 60s linear infinite; /* Increased from 20s to 60s */

  background: radial-gradient(circle at 30% 30%, #f0e68c, #daa520);

  box-shadow:

    inset -2px -2px 4px rgba(0, 0, 0, 0.3),

    0 0 8px rgba(218, 165, 32, 0.6);

}

@keyframes orbit {

  0% {

    transform: rotate(0deg) translateX(100px) rotate(0deg);

  }

  100% {

    transform: rotate(360deg) translateX(100px) rotate(-360deg);

  }

}

.shooting-stars {

  position: absolute;

  top: 0;

  left: 0;

  width: 100%;

  height: 100%;

}

.shooting-star {

  position: absolute;

  height: 2px;

  background: linear-gradient(90deg, #ffffff, transparent);

  animation: shoot 3s ease-out infinite;

}

@keyframes shoot {

  0% {

    transform: translateX(-100px) translateY(100px);

    opacity: 1;

  }

  70% {

    opacity: 1;

  }

  100% {

    transform: translateX(1000px) translateY(-1000px);

    opacity: 0;

  }

}

.asteroid-belt {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%) rotateX(75deg);

  width: 350px;

  height: 350px;

  border-radius: 50%;

}

.asteroid {

  position: absolute;

  background: #555;

  border-radius: 50%;

  top: 50%;

  left: 50%;

  transform-origin: 175px 0;

  animation: rotate 20s linear infinite;

}

@keyframes rotate {

  0% {

    transform: rotate(0deg) translateX(175px) rotate(0deg);

  }

  100% {

    transform: rotate(360deg) translateX(175px) rotate(-360deg);

  }

更多推荐