宇宙画布:纯 CSS+JS 实现交互式深空艺术

12 阅读8分钟

大家好,我是前端开发者。在前端技术不断发展的今天,CSS 早已不只是用来布局和美化页面的工具,它还能成为我们创作视觉艺术的画笔。今天给大家带来一个纯 CSS + 原生 JS 实现的交互式深空场景,无需任何图形库,就能在浏览器里呈现出繁星闪烁、星云流动、行星运转、流星划过的沉浸式宇宙画面。 项目已开源,大家可以直接下载运行,也能基于它二次创作属于自己的星空。


一、项目效果与核心亮点

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

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

核心技术点:

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

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

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

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

html

预览

<!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 是这个项目的核心,负责所有视觉效果、动画、质感的实现,每一行都加了注释,方便理解。

css

/* 全局初始化:清除默认边距,全屏展示,隐藏滚动条 */
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 负责批量生成星星、星系、流星、小行星,随机化大小、位置、动画时长,让星空更自然不呆板。

javascript

运行

/**
 * 动态创建天体元素:星星、星系、流星、小行星
 * 批量生成+随机属性,提升效率与真实感
 */
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 组合技巧:

css

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

2. 3D 视觉效果

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

3. 性能优化要点

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

四、项目拓展方向

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

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

五、演示地址


六、总结

这个深空艺术项目,完美展示了CSS 的艺术创作能力JS 的动态操控能力。不需要复杂的图形库,只用基础前端技术,就能打造出惊艳的视觉效果。

对于前端开发者来说,CSS 艺术不仅能提升对样式、动画、变换的理解,还能激发创作灵感。希望这个项目能给大家带来启发,动手试试吧,用代码画出属于自己的宇宙!