导读:本期聚焦于小伙伴创作的《纯CSS实现太阳系运转模型动画:地球绕太阳与月球绕地球的双层轨道》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《纯CSS实现太阳系运转模型动画:地球绕太阳与月球绕地球的双层轨道》有用,将其分享出去将是对创作者最好的鼓励。

纯CSS实现太阳系运转模型动画

在网页开发中,使用纯CSS实现动画不仅可以减少对JavaScript的依赖,还能让页面更加流畅和简洁。本文将详细介绍如何仅用HTML和CSS制作一个包含太阳、地球和月亮的简易运转模型动画。这个动画模拟了地球绕太阳公转、月球绕地球公转的双层轨道运动,并且地球本身还会自转。

核心思路是通过CSS animation配合transform-origin设置旋转中心,再利用嵌套的<div>结构实现轨道层级关系。整个动画不需要任何JavaScript代码,完全由CSS驱动。

准备工作:HTML结构设计

首先需要为每个天体创建对应的容器。太阳作为中心,放置在最外层;地球容器包含地球本身,并负责绕太阳公转;月球容器包含月球本身,并嵌套在地球容器内部,随地球一起运动,同时自身还绕地球公转。注意,为了让月球正确绕地球旋转,月球容器必须相对于地球容器定位,并且月球本身的transform-origin要设置在地球容器中心。

以下是一个合理的HTML结构:

<div class="solar-system">
  <div class="sun"></div>
  <div class="earth-orbit">
    <div class="earth">
      <div class="moon-orbit">
        <div class="moon"></div>
      </div>
    </div>
  </div>
</div>

解释一下各部分的作用:

  • solar-system:最外层容器,负责整体定位和背景。
  • sun:太阳本体,固定显示在中心。
  • earth-orbit:地球轨道的容器,通过旋转这个容器来实现地球的公转。
  • earth:地球本体,同时作为月球轨道容器的父级。
  • moon-orbit:月球轨道容器,通过旋转使月球绕地球公转。
  • moon:月球本体。

CSS核心动画原理

实现多层公转的关键在于设置正确的transform-origin。以地球公转为例:地球容器earth-orbittransform-origin应该设置为太阳的中心点,即50% 50%(相对父容器),但为了简化,通常将earth-orbit的宽高设为轨道直径,并利用position: absolute将其左上角定位到太阳中心偏移。

更常用的方法是:将earth-orbit放置在与太阳相同大小的容器中,通过position: absolute; left: 50%; top: 50%;使轨道容器以太阳中心为旋转基点。然后通过transform: rotate()动画带动整个轨道容器旋转,而地球则固定在轨道容器内部远离中心的位置(例如距左边缘恰好等于轨道半径)。这样就形成了公转效果。

同理,月球轨道容器moon-orbit也以地球中心为旋转基点,月球固定在月球轨道容器内部。

具体实现步骤

下面给出完整的CSS代码,并逐段解释关键部分。

1. 基础布局与太阳样式

设置整个场景的大小和背景,让太阳居中显示,并添加发光效果。

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: #000;
}

.solar-system {
  position: relative;
  width: 400px;
  height: 400px;
}

.sun {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60px;
  height: 60px;
  background: radial-gradient(circle, #ff9a00, #ff3300);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 40px #ff6600;
}

太阳使用radial-gradient模拟渐变,并添加box-shadow使其发光。

2. 地球轨道与地球本体

地球的轨道是一个旋转的容器,地球本身固定在容器内。轨道容器的旋转轴心是太阳中心,因此轨道容器需要定位到太阳中心,并且其尺寸应该等于轨道直径(例如太阳半径+地球公转半径的两倍)。实际上我们更常用的是让轨道容器完全包裹太阳,通过left: 50%; top: 50%;配合margin-left: -半径; margin-top: -半径;使其中心与太阳重合。但为了让代码更直观,可以这样处理:轨道容器宽高为轨道直径,然后position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);,这样轨道容器中心与太阳中心对齐。然后在地球轨道容器内部,地球元素被放置在轨道边缘(例如距离左边为轨道半径的位置),并通过旋转整个容器实现公转。

注意:由于地球轨道容器本身旋转,地球也会随之绕太阳旋转。

.earth-orbit {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 300px;  /* 轨道直径 */
  height: 300px;
  transform: translate(-50%, -50%);
  animation: earthOrbit 10s linear infinite;
}

.earth {
  position: absolute;
  top: 50%;
  left: 0;       /* 将地球放在轨道最左边(最远处) */
  width: 30px;
  height: 30px;
  background: radial-gradient(circle at 30% 30%, #4a90d9, #1e3a5f);
  border-radius: 50%;
  transform: translate(0, -50%);  /* 使地球垂直居中 */
  box-shadow: 0 0 10px #2a6bb0;
  /* 为了让地球本身自转,可以添加自转动画 */
  animation: earthSpin 2s linear infinite;
}

公转动画earthOrbit很简单:

@keyframes earthOrbit {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

@keyframes earthSpin {
  from { transform: translate(0, -50%) rotate(0deg); }
  to { transform: translate(0, -50%) rotate(360deg); }
}

注意:earthOrbit中使用了translate(-50%, -50%)使轨道容器始终居中,然后叠加旋转。这样地球就会围绕太阳旋转。而earthSpin让地球自身旋转,通过translate(0, -50%)修正位置,因为地球在轨道容器中已经用left: 0定位,旋转中心为地球中心。

3. 月球轨道与月球本体

月球轨道容器moon-orbit应当嵌套在地球容器内部,并且以地球中心为旋转基点。这里需要特别注意:moon-orbit的父元素是earth,而earth本身是相对于earth-orbit定位的。为了简化,我们可以将moon-orbit的尺寸设置得与地球宽度一致,然后用position: absolutemoon-orbit覆盖在地球上,再通过transform-origin设置旋转中心为地球中心。但是更常见的方法是:把moon-orbit也做成一个与地球同心的大容器,类似地球轨道的做法。但这里地球容器的尺寸只有30px(地球直径),因此月球轨道容器必须小于地球容器?不对,月球轨道半径相对于地球应该很小。简单有效的方法是:将moon-orbit设置成一个较大的容器(例如直径80px),并将其中心对齐到地球中心,然后月球元素放在该容器内边缘。但这样月球轨道容器会覆盖地球,可能遮挡地球。为了不遮挡,我们可以将月球轨道容器放在地球容器的内部,并通过transform-origin设置为地球中心(即容器自身的50% 50%)。由于容器必须足够大以至于能包含月球轨道,我们可以将moon-orbit的宽高设为地球直径的两倍加月球轨道半径的两倍,但更优雅的做法是使用伪元素或者将月球放在地球的子级中,通过transform: rotate()结合translateX来模拟轨道。这里我采用另一种经典方法:将月球轨道容器设置为与地球容器同宽高,但overflow: visible,然后月球元素通过transform: translateX(距离) rotate(...)来实现绕地球公转。但为了保持代码一致性,我选择将月球轨道容器作为一个独立的绝对定位元素,其左上角位于地球中心,然后通过transform-origin为轨道容器的中心(即地球中心),月球元素放在轨道容器内部。由于轨道容器尺寸较小,月球会超出容器?没关系,设置overflow: visible即可。

为了简化并避免混乱,下面给出更清晰的实现方案:直接将月球轨道容器嵌套在地球容器内部,且其尺寸等于月球轨道直径,并通过CSS将其中心与地球中心对齐。在地球容器(earth)内部,月球轨道容器moon-orbitposition: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);,然后通过animation旋转这个容器,月球元素则放在轨道容器的边缘(例如left: 0; top: 50%;)。但是注意,此时月球轨道容器的旋转中心默认是自身中心,而自身中心与地球中心重合(因为transform: translate(-50%, -50%)),所以旋转时月球就会绕地球公转。好,这个方案可行。

以下是月球部分的CSS:

.moon-orbit {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 80px;   /* 月球轨道直径 */
  height: 80px;
  transform: translate(-50%, -50%);
  animation: moonOrbit 3s linear infinite;
}

.moon {
  position: absolute;
  top: 50%;
  left: 0;       /* 放在轨道边缘 */
  width: 12px;
  height: 12px;
  background: radial-gradient(circle at 30% 30%, #ccc, #888);
  border-radius: 50%;
  transform: translate(0, -50%);
  box-shadow: 0 0 5px #aaa;
}

@keyframes moonOrbit {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

注意:月球轨道容器moon-orbit的父元素是earth,而earth本身是position: absolute,且其宽度为30px。为了能让moon-orbit正确显示,earth需要设置overflow: visible,否则月球会被裁剪。另外,moon-orbit的宽高80px大于父容器earth的30px,但父容器没有设置overflow: hidden,所以没问题。

4. 调整细节与完整代码

为了让效果更逼真,可以添加一些额外的样式,例如轨道线(用border或伪元素),以及让太阳脉动。下面给出完整的HTML和CSS代码。注意代码中所有HTML特殊字符均已转义。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>纯CSS太阳-地球-月亮模型</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      background: #000;
    }
    .solar-system {
      position: relative;
      width: 400px;
      height: 400px;
    }
    .sun {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 60px;
      height: 60px;
      background: radial-gradient(circle, #ff9a00, #ff3300);
      border-radius: 50%;
      transform: translate(-50%, -50%);
      box-shadow: 0 0 40px #ff6600;
      animation: pulse 4s ease-in-out infinite;
    }
    @keyframes pulse {
      0%, 100% { transform: translate(-50%, -50%) scale(1); box-shadow: 0 0 40px #ff6600; }
      50% { transform: translate(-50%, -50%) scale(1.1); box-shadow: 0 0 60px #ff6600; }
    }

    .earth-orbit {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 280px;
      height: 280px;
      transform: translate(-50%, -50%);
      animation: earthOrbit 12s linear infinite;
      /* 可添加轨道线 */
      border: 1px dashed rgba(255, 255, 255, 0.2);
      border-radius: 50%;
    }
    .earth {
      position: absolute;
      top: 50%;
      left: 0;
      width: 32px;
      height: 32px;
      background: radial-gradient(circle at 35% 35%, #4a90d9, #1e3a5f);
      border-radius: 50%;
      transform: translate(0, -50%);
      box-shadow: 0 0 10px #2a6bb0;
      animation: earthSpin 2s linear infinite;
      overflow: visible; /* 允许月球轨道超出 */
    }
    @keyframes earthOrbit {
      from { transform: translate(-50%, -50%) rotate(0deg); }
      to { transform: translate(-50%, -50%) rotate(360deg); }
    }
    @keyframes earthSpin {
      from { transform: translate(0, -50%) rotate(0deg); }
      to { transform: translate(0, -50%) rotate(360deg); }
    }

    .moon-orbit {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 80px;
      height: 80px;
      transform: translate(-50%, -50%);
      animation: moonOrbit 4s linear infinite;
      border: 1px dashed rgba(255, 255, 255, 0.15);
      border-radius: 50%;
    }
    .moon {
      position: absolute;
      top: 50%;
      left: 0;
      width: 14px;
      height: 14px;
      background: radial-gradient(circle at 30% 30%, #ccc, #888);
      border-radius: 50%;
      transform: translate(0, -50%);
      box-shadow: 0 0 5px #aaa;
    }
    @keyframes moonOrbit {
      from { transform: translate(-50%, -50%) rotate(0deg); }
      to { transform: translate(-50%, -50%) rotate(360deg); }
    }
  </style>
</head>
<body>
  <div class="solar-system">
    <div class="sun"></div>
    <div class="earth-orbit">
      <div class="earth">
        <div class="moon-orbit">
          <div class="moon"></div>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

上述代码实现了太阳发光脉动、地球公转自转、月球绕地球公转。你可以调整动画时间(如12s2s4s)改变速度,也可以修改轨道半径(通过更改earth-orbitmoon-orbit的宽高)和天体大小。

总结

通过合理地使用CSS动画、transformtransform-origin,我们可以不依赖任何JavaScript模拟出太阳系中太阳、地球、月球的基本运动关系。这种技术不仅适用于教育演示,也可以用于网页中的装饰性动画。需要注意的是,公转的实现依赖于元素容器的旋转,而容器内部的天体则固定在边缘。通过嵌套多层这样的结构,可以构建出更复杂的轨道系统。希望本文能帮助你掌握纯CSS实现多层公转动画的技巧。

纯CSS动画CSS_太阳系模型transform旋转地球月球公转动画制作教程

免责声明:已尽一切努力确保本网站所含信息的准确性。网站部分内容来源于网络或由用户自行发表,内容观点不代表本站立场。本站是个人网站免费分享,内容仅供个人学习、研究或参考使用,如内容中引用了第三方作品,其版权归原作者所有。若内容触犯了您的权益,请联系我们进行处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。前端、网络、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握网站开发与运维所需的核心技术栈。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端逻辑,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。