从中秋之月到宇宙洪荒-纯CSS实现3d星球

2,148 阅读3分钟

“我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

背景

马上中秋了,画个月亮吧,普通的月亮太不真实,就来个月球吧。光一个月球太简单就来个地月日吧,再加入八大行星,加个宇宙背景,嗯,完美的可以去参加掘金中秋技术征文大赛了!

月球的实现

我们画个圆,然后想让他变成球,这个挺有难度。所以我们换个角度,通过视觉效果来画星球。我们可以利用一个有星球背景图的元素移动,外部元素作为圆形,超出内部区域隐藏,再加个倾斜的角度(transform: rotateZ(25deg);)这样看起来就会像星球在旋转,代码如下:

<div class="ps-center moon-box">
  <div class="moon"></div>
</div>
.ps-center {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin: auto;
}
.moon-box {
  width: 100px;
  height: 100px;
  overflow: hidden;
  border-radius: 50%;
  transform-style: preserve-3d;
  transform: rotateZ(25deg);
}
.moon{
  width: 400px;
  height: 100px;
  background: url(./img/moon.jpg);
  background-size: 100% 100%;
  position: absolute;
  left: -200px;
  animation: moonRole 3s linear infinite;
}
@keyframes moonRole {
  0% {
    transform: translate(0);
  }
  100% {
    transform: translate(200px);
  }
}

注意:背景元素宽度大小是月亮盒子元素宽度的4倍,背景图要俩个相同的月球平面展开图,平铺,因为是上下左右居中的,所以背景元素左移背景宽度的一半,做平移一半背景的动效,就刚好像旋转一周 moonrole.gif 但是,看着不够3d啊,没关系,月球是绕着地球转的,有了这个就更立体了,让我们进入下一步

月球公转

按照月球画个地球,然后让月球绕着地球旋转,嗯,就这么简单。但是由里向外这样旋转怎么实现呢?我们都知道在真实的视觉空间里会有近大远小的情况,我们只需要平移星球,然后根据近大远小的规则放缩星球就会呈现出由外到里绕地球公转的感觉。代码如下:

<div class="ps-center em-box">
  <div class="ps-center earth-box">
    <div class="earth"></div>
  </div>
  <div class="ps-center moon-box">
    <div class="moon"></div>
  </div>
</div>
.em-box {
  transform-style: preserve-3d;
  perspective-origin: 50% 50%;
  width: 600px;
  height: 600px;
  transform: rotateZ(20deg);
}
.earth-box {
  width: 200px;
  height: 200px;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: 0 0 10px rgba(5, 97, 184, 0.952), -1px -2px 10px rgba(256,256,256,0.5) inset;
}
.earth {
  width: 800px;
  height: 200px;
  background: url(./img/earth.jpeg);
  background-size: 100% 100%;
  position: absolute;
  left: -400px;
  animation: earthRole 3s linear infinite;
}
@keyframes earthRole {
  0% {
    transform: translate(0);
  }
  100% {
    transform: translate(400px);
  }
}
.moon-box {
  width: 100px;
  height: 100px;
  overflow: hidden;
  border-radius: 50%;
  box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
  animation: roleEarth 3s linear infinite;
}
@keyframes roleEarth {
  0% {
    transform: translateX(-400px) translateZ(0) scale(1);
  }
  25% {
    transform: translateX(0) translateZ(400px) scale(1.5);
  }
  50% {
    transform: translateX(400px) translateZ(0) scale(1);
  }
  75% {
    transform: translateX(0) translateZ(-400px) scale(0.5);
  }
  100% {
    transform: translateX(-400px) translateZ(0) scale(1);
  }
}
.moon{
  width: 400px;
  height: 100px;
  background: url(./img/moon.jpg);
  background-size: 100% 100%;
  position: absolute;
  left: -200px;
  animation: moonRole 3s linear infinite;
}
@keyframes moonRole {
  0% {
    transform: translate(0);
  }
  100% {
    transform: translate(200px);
  }
}

注意:父元素倾斜,子元素就跟着倾斜了 em.gif

地月日

接下来我们继续画太阳吧,然后让地球和月亮整体绕着太阳公转,实现地月日。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>moon</title>
  <style>
    .content-box {
      position: relative;
      width: 1000px;
      height: 600px;
      transform-style: preserve-3d;
      perspective-origin: 50% 50%;
      transform: rotateZ(25deg);
    }
    .ps-center {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      margin: auto;
    }
    .sun-box {
      width: 200px;
      height: 200px;
      border-radius: 50%;
      overflow: hidden;
      box-shadow: 0 0 20px rgba(247, 125, 4, 0.961), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .sun {
      width: 400px;
      height: 200px;
      position: absolute;
      left: -200px;
      background: url(./img/sun.jpg);
      background-size: 100% 100%;
      animation: sunRole 5s linear infinite;
    }
    @keyframes sunRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(200px);
      }
    }

    .em-box {
      transform-style: preserve-3d;
      perspective-origin: 50% 50%;
      width: 400px;
      height: 400px;
      animation: roleSun 10s linear infinite;
    }
    .earth-box {
      transform: rotateZ(20deg);
      width: 50px;
      height: 50px;
      overflow: hidden;
      border-radius: 50%;
      box-shadow: 0 0 10px rgba(5, 97, 184, 0.952), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .earth {
      width: 200px;
      height: 50px;
      background: url(./img/earth.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -100px;
      animation: earthRole 3s linear infinite;
    }
    @keyframes earthRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(100px);
      }
    }
    .moon{
      width: 120px;
      height: 30px;
      background: url(./img/moon.jpg);
      background-size: 100% 100%;
      position: absolute;
      left: -60px;
      animation: moonRole 1s linear infinite;
    }
    @keyframes moonRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(60px);
      }
    }
    .moon-box {
      width: 30px;
      height: 30px;
      overflow: hidden;
      border-radius: 50%;
      animation: roleEarth 3s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    @keyframes roleEarth {
      0% {
        transform: translateX(-80px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(200px) scale(1.5);
      }
      50% {
        transform: translateX(80px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-200px) scale(0.5);
      }
      100% {
        transform: translateX(-80px) translateZ(0) scale(1);
      }
    }
    @keyframes roleSun {
      0% {
        transform: translateX(-300px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(400px) scale(1.5);
      }
      50% {
        transform: translateX(300px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-400px) scale(0.5);
      }
      100% {
        transform: translateX(-300px) translateZ(0) scale(1);
      }
    }
  </style>
</head>
<body>
  <div class="content-box">
    <div class="ps-center sun-box">
      <div class="sun"></div>
    </div>
    <div class="ps-center em-box">
      <div class="ps-center earth-box">
        <div class="earth"></div>
      </div>
      <div class="ps-center moon-box">
        <div class="moon"></div>
      </div>
    </div>
  </div>
</body>
</html>

注意:绕谁转就给谁的父元素设置transform-style: preserve-3d; ems.gif

太阳系

再把八大行星加进来绕太阳公转(模仿地月整体,搬砖苦力活儿)太阳系星体就完成了,最后加个好看的宇宙星图背景,就是宇宙(假的)。全部代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
    }
    .bg-box {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 100%;
      background: url(./img/yuzhou.jpeg);
      background-size: 100% 100%;
    }
    .content-box {
      position: relative;
      width: 1000px;
      height: 600px;
      transform-style: preserve-3d;
      perspective-origin: 50% 50%;
      transform: rotateZ(25deg);
    }
    .ps-center {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      margin: auto;
    }
    .sun-box {
      width: 200px;
      height: 200px;
      border-radius: 50%;
      overflow: hidden;
      box-shadow: 0 0 20px rgba(247, 125, 4, 0.961), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .sun {
      width: 400px;
      height: 200px;
      position: absolute;
      left: -200px;
      background: url(./img/sun.jpg);
      background-size: 100% 100%;
      animation: sunRole 5s linear infinite;
    }
    @keyframes sunRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(200px);
      }
    }
    .em-box {
      transform-style: preserve-3d;
      perspective-origin: 50% 50%;
      width: 400px;
      height: 400px;
      animation: roleSun 10s linear infinite;
    }
    .earth-box {
      transform: rotateZ(20deg);
      width: 50px;
      height: 50px;
      overflow: hidden;
      border-radius: 50%;
      box-shadow: 0 0 10px rgba(5, 97, 184, 0.952), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .earth {
      width: 200px;
      height: 50px;
      background: url(./img/earth.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -100px;
      animation: earthRole 3s linear infinite;
    }
    .moon{
      width: 120px;
      height: 30px;
      background: url(./img/moon.jpg);
      background-size: 100% 100%;
      position: absolute;
      left: -60px;
      animation: moonRole 1s linear infinite;
    }
    .moon-box {
      width: 30px;
      height: 30px;
      overflow: hidden;
      border-radius: 50%;
      animation: roleEarth 3s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .water{
      width: 160px;
      height: 40px;
      background: url(./img/water.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -80px;
      animation: waterRole 2s linear infinite;
    }
    .water-box {
      width: 40px;
      height: 40px;
      overflow: hidden;
      border-radius: 50%;
      animation: waterRoleSun 7s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .gold{
      width: 200px;
      height: 50px;
      background: url(./img/gold.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -100px;
      animation: goldRole 2s linear infinite;
    }
    .gold-box {
      width: 50px;
      height: 50px;
      overflow: hidden;
      border-radius: 50%;
      animation: goldRoleSun 2s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .fire{
      width: 180px;
      height: 45px;
      background: url(./img/fire.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -90px;
      animation: fireRole 2s linear infinite;
    }
    .fire-box {
      width: 45px;
      height: 45px;
      overflow: hidden;
      border-radius: 50%;
      animation: fireRoleSun 3s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .mood{
      width: 320px;
      height: 80px;
      background: url(./img/mood.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -160px;
      animation: moodRole 2s linear infinite;
    }
    .mood-box {
      width: 80px;
      height: 80px;
      overflow: hidden;
      border-radius: 50%;
      animation: moodRoleSun 6s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    .soil{
      width: 280px;
      height: 70px;
      background: url(./img/soil.jpeg);
      background-size: 100% 100%;
      position: absolute;
      left: -140px;
      animation: soilRole 2s linear infinite;
    }
    .soil-box {
      width: 70px;
      height: 70px;
      overflow: hidden;
      border-radius: 50%;
      animation: soilRoleSun 5s linear infinite;
      box-shadow: -4px 0 10px rgba(256,256,256,0.3), -1px -2px 10px rgba(256,256,256,0.5) inset;
    }
    @keyframes earthRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(100px);
      }
    }
    @keyframes moonRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(60px);
      }
    }
    @keyframes waterRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(80px);
      }
    }
    @keyframes goldRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(100px);
      }
    }
    @keyframes fireRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(90px);
      }
    }
    @keyframes moodRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(160px);
      }
    }
    @keyframes soilRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(140px);
      }
    }
    @keyframes skykingRole {
      0% {
        transform: translate(0);
      }
      100% {
        transform: translate(120px);
      }
    }
    @keyframes roleSun {
      0% {
        transform: translateX(-300px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(400px) scale(1.5);
      }
      50% {
        transform: translateX(300px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-400px) scale(0.5);
      }
      100% {
        transform: translateX(-300px) translateZ(0) scale(1);
      }
    }
    @keyframes waterRoleSun {
      0% {
        transform: translateX(-150px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(200px) scale(1.5);
      }
      50% {
        transform: translateX(150px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-200px) scale(0.5);
      }
      100% {
        transform: translateX(-150px) translateZ(0) scale(1);
      }
    }
    @keyframes goldRoleSun {
      0% {
        transform: translateX(-220px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(300px) scale(1.5);
      }
      50% {
        transform: translateX(220px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-300px) scale(0.5);
      }
      100% {
        transform: translateX(-220px) translateZ(0) scale(1);
      }
    }
    @keyframes fireRoleSun {
      0% {
        transform: translateX(-350px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(500px) scale(1.5);
      }
      50% {
        transform: translateX(350px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-500px) scale(0.5);
      }
      100% {
        transform: translateX(-350px) translateZ(0) scale(1);
      }
    }
    @keyframes moodRoleSun {
      0% {
        transform: translateX(-450px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(600px) scale(1.5);
      }
      50% {
        transform: translateX(450px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-600px) scale(0.5);
      }
      100% {
        transform: translateX(-450px) translateZ(0) scale(1);
      }
    }
    @keyframes soilRoleSun {
      0% {
        transform: translateX(-550px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(700px) scale(1.5);
      }
      50% {
        transform: translateX(550px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-700px) scale(0.5);
      }
      100% {
        transform: translateX(-550px) translateZ(0) scale(1);
      }
    }
    @keyframes roleEarth {
      0% {
        transform: translateX(-80px) translateZ(0) scale(1);
      }
      25% {
        transform: translateX(0) translateZ(200px) scale(1.5);
      }
      50% {
        transform: translateX(80px) translateZ(0) scale(1);
      }
      75% {
        transform: translateX(0) translateZ(-200px) scale(0.5);
      }
      100% {
        transform: translateX(-80px) translateZ(0) scale(1);
      }
    }
  </style>
</head>
<body>
  <div class="bg-box">
    <div class="content-box">
      <div class="ps-center sun-box">
        <div class="sun"></div>
      </div>
      <div class="ps-center em-box">
        <div class="ps-center earth-box">
          <div class="earth"></div>
        </div>
        <div class="ps-center moon-box">
          <div class="moon"></div>
        </div>
      </div>
      <div class="ps-center gold-box">
        <div class="gold"></div>
      </div>
      <div class="ps-center mood-box">
        <div class="mood"></div>
      </div>
      <div class="ps-center water-box">
        <div class="water"></div>
      </div>
      <div class="ps-center fire-box">
        <div class="fire"></div>
      </div>
      <div class="ps-center soil-box">
        <div class="soil"></div>
      </div>
    </div>
  </div>
</body>
</html>

universe.gif 最后发现星球大小及间距啥的没有调好,窗口放不下了QAQ,只画了金木水火土五颗行星。。。后边的就留给聪明又勤奋好学的大家补充吧。还有土星🪐的环状卫星带,如果大家实现了,欢迎下边评论交流!

最后,祝大家中秋快乐!希望中个奖!!!手动@掘金酱