乐趣区

关于前端:原来3D感空间行星轨迹是这样画的

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

背景

点击查看太阳、地球、月亮 3D 旋转

点击查看太阳、地球、月亮 3D 旋转 2

点击查看太阳、地球、月亮 3D 旋转源码

中秋佳节行将到来,远在他乡的孩子们马上能够回家和父母一起吃月饼,看月亮,聊聊工作、谈谈现实,想想还挺惬意。

低头望向天空时,你是否想晓得太阳、地球、月亮的绕行轨迹如何通过 css3 来实现?来吧,这篇文章会从零和你一起学习如果画一个 3D 小球 如何绘制漫天的繁星 如何实现行星轨迹 3D 图

要害元素

  1. 一个旋转的 3D 球
  2. 漫天繁星,会眨眼睛那种哦
  3. 旋转的行星轨道

如何画一个 3D 球

您也能够间接点击这里查看,成果更好

先观赏几张图

在画球之前咱们先观赏几张图

《冰河世纪》的小松鼠
隔着屏幕我好像都碰着到这灵活的鼻子

透过显示器的枪?

摸摸狗头

再画集体人都会的圆

看完下面的图,聪慧的你肯定猜到了,咱们只有在 2d 立体上加几天竖线,3D 的感觉就进去了

html


<div class="ball-container">
  <div class="ball-bg"></div>
  <div class="ball"></div>
</div>

css

.ball-container{
  width: 200px;
  height: 200px;
  border-radius: 50%;
  perspective: 500px;
  position: relative;
}

.ball {
  transform-style: preserve-3d;
  position: absolute;
  width: 100%;
  height: 100%;
}

.ball-bg{
  width: 100%;
  height: 100%;
  position: absolute;
  border-radius: 50%;
  background-image: linear-gradient(
    45deg,
    #ff9a9e 0%,
    #fad0c4 99%,
    #fad0c4 100%
  );
}

通过下面的代码,咱们失去的是一个粉粉的圆,接下来试试加上几条线,能不能有 3D 的感觉

添上 4 条竖线

.ball-line {
  width: 100%;
  height: 100%;
  background-color: transparent;
  border: solid 0.5px #fad0c4;
  border-radius: 50%;
  margin: -0.5px;
  position: absolute;
  box-sizing: border-box;
}

.ball-line:nth-of-type(1) {transform: rotateY(45deg);
}
.ball-line:nth-of-type(2) {transform: rotateY(90deg);
}
.ball-line:nth-of-type(3) {transform: rotateY(135deg);
}
.ball-line:nth-of-type(4) {transform: rotateY(180deg);
}

为了让线不那么粗影响整体球的感觉,咱们加了 0.5px,看起来有一点点 3d 的感觉了,最初让球旋转起来试试

让球旋转起来


@keyframes rotate {
  0%{transform: rotateY(0) rotateX(0);
  }

  100%{transform: rotateY(360deg) rotateX(360deg);
  }
}

.ball {
  /* 增加动画 */
  animation: rotate 10s infinite linear; 
}

旋转的 3D 球就画好啦

再画一副漫天繁星的天空

闭上眼睛回忆一下你记忆中夜晚的天空,闪动的星星是那么的平静, 安详,像是一只只亮堂的眼睛, 又像一盏盏亮晶晶的银灯。

dom 构造

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

要害 css


 @keyframes shine {
  0% {opacity: 0.5;}
  100% {opacity: 1;}
}

要害 js

思考星星的数量泛滥,且宽高不同最好,这里咱们通过 js 来动静生成星星

  const $ = document.querySelector.bind(document);
  const $body = $("body");
  const canvasWidth = $body.offsetWidth;
  const canvasHeight = $body.offsetHeight;
  // 创立一个带自定义款式的 dom
  const createElement = (styles, tag = "div") => {const ele = document.createElement(tag);

    Object.keys(styles).forEach((attr) => {ele.style[attr] = styles[attr];
    });

    return ele;
  };

  const drawStars = () => {
    // 创立文档碎片,缓存 dom 片段,缩小 dom 操作
    const $starFragment = document.createDocumentFragment();
    const $stars = $(".stars");
    /*
    // 创立任意数量的星星
      1. 地位不同
      2. 大小不同
      3. 动画延时不同
    */
    const createStar = (size, num) => {while (num--) {const left = Math.random() * (canvasWidth - size) + "px";
        const top = Math.random() * (canvasHeight - size) + "px";        const width = size + "px";
        const delay = Math.random() * 5;
        const styles = {
          width,
          height: width,
          left,
          top,
          borderRadius: "50%",
          position: "absolute",
          background: "#ffffff",
          animation: `shine 2s linear ${delay}s infinite`,
        };
        const $star = createElement(styles);

        $starFragment.appendChild($star);
      }
    };
    // 创立不同大小的星星
    createStar(1, 500);
    createStar(2, 40); 
    createStar(3, 30);
    createStar(4, 20);

    $stars.appendChild($starFragment)};

    drawStars();

太阳、地球、月亮静止全景

有了后面的星空背景以及 3D 小球根底,接下来咱们能够开始画真正的运行轨迹图啦!!!

把本人转动的太阳先画进去

太阳无疑是最亮的崽,咱们先把他给整进去


<div class="sun">
  <div class="ball-container">
    <div class="ball">
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
    </div>
    <div class="ball-light"></div>
  </div>
</div>
.ball-container {
  width: 70px;
  height: 70px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  left: 50%;
  margin-left: -35px;
  top: -35px;
  animation: rotateContainer 20s linear infinite;
}

.ball {
  transform-style: preserve-3d;
  border-radius: 50%;
  width: 100%;
  height: 100%;
  animation: rotateSelf 10s infinite linear;
  position: absolute;
}

.ball-light {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  position: absolute;
}

.ball-line {
  width: 100%;
  height: 100%;
  background-color: transparent;
  border: solid 0.5px #fcd670;
  border-radius: 50%;
  margin: -1px;
  position: absolute;
}

.ball-line:nth-of-type(1) {transform: rotateY(45deg);
}

.ball-line:nth-of-type(2) {transform: rotateY(90deg);
}

.ball-line:nth-of-type(3) {transform: rotateY(135deg);
}

.ball-line:nth-of-type(4) {transform: rotateY(180deg);
}

.sun {
  transform-style: preserve-3d;
  position: absolute;
}

.sun .ball-container {
  width: 100px;
  height: 100px;
  animation: none;
}

.sun .ball-light {
  background-image: linear-gradient(
    to right,
    #ff8177 0%,
    #ff867a 0%,
    #ff8c7f 21%,
    #f99185 52%,
    #cf556c 78%,
    #b12a5b 100%
  );
  box-shadow: 0 0 100px #ff8177;
}

.sun .ball-line {border-color: #ff8177;}

/* 球本身的旋转 */
@keyframes rotateSelf {
  0% {transform: rotateY(0) rotateX(0);
  }

  100% {transform: rotateY(360deg) rotateX(360deg);
  }
}

地球绕着太阳转

地球绕着太阳转次要须要思考两个关键点:1。椭圆形轨道 2. 地球绕着椭圆形轨道旋转

地球绕行轨道

如何能力画出这样的轨道图?其实能够看成是一个侧面的圆沿着 X 轴旋转了肯定的角度,让其看起来比拟有空间感

第一步:先画出侧面的圆

<div class="earch"></div>

.earch {
  transform-style: preserve-3d;
  position: relative;
  width: 50vw;
  height: 50vw;
  border: solid 0.5px #ffffff;
  border-radius: 50%;
  box-shadow: 0 0 22px #fff;
}

第二步:绕着 X 轴旋转


.earch {
  transform-style: preserve-3d;
  position: relative;
  width: 60vw;
  height: 60vw;
  border: solid 0.5px #ffffff;
  border-radius: 50%;
  transform: rotateX(75deg);
  box-shadow: 0 0 22px #fff;
}

把旋转地球画进去

地球的画法和太阳没有太大的区别,这里咱们次要想一下如何能力画出一个绕着方才画出的轨迹静止的地球

公园里的这个器材大家应该都玩过哈,人站上去时,转动底部的罗盘,罗盘在转,人也就跟着转了。利用到这里,能够把轨迹比作是踩脚的罗盘,而人则是地球。

让轨迹静止,球则绝对于轨迹静止,轨迹静止了,球天然也就看起来在动了。

<!-- 内部的罗盘 -->
<div class="earch">
  <!-- 地球 -->
  <div class="ball-container">
    <div class="ball">
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
    </div>
    <div class="ball-light"></div>
  </div>
</div>

/* 轨道旋转 */
/* 因为须要放弃歪斜的角度,所以初始和终态都是 rotateX(75deg) */
@keyframes rotateTrack {
  0% {transform: rotateX(75deg) rotateZ(0);
  }
  100% {transform: rotateX(75deg) rotateZ(360deg);
  }
}

 /* 打消轨道旋转对子元素的影响 */
@keyframes rotateContainer {
  0% {transform: rotateZ(0) rotateX(-75deg);
  }
  100% {transform: rotateZ(-360deg) rotateX(-75deg);
  }
}

.earch {
  transform-style: preserve-3d;
  position: relative;
  width: 60vw;
  height: 60vw;
  border: solid 0.5px #ffffff;
  border-radius: 50%;
  transform: rotateX(75deg);
  animation: rotateTrack 20s linear infinite;
  box-shadow: 0 0 22px #fff;
}

.earch .ball-light {background-image: linear-gradient(to top, #37ecba 0%, #72afd3 100%);
  box-shadow: 0 0 1000px #72afd3;
}

.earch .ball-line {border-color: #72afd3;}

于是旋转的地球也画好啦!最初只剩下离绕着地球旋转的月亮了

月亮绕着太阳转

整体思路和地球绕着月亮转是差不多的,然而须要留神的是

  1. 月亮绕行地球的速度大于地球绕行太阳的速度,
  2. 留神打消地球轨迹旋转对月亮整体的影响
<div class="earch">
  <div class="ball-container">
    <div class="ball">
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
      <div class="ball-line"></div>
    </div>
    <div class="ball-light"></div>
  </div>
  <!-- 月亮局部 -->
  <div class="moon-container">
    <div class="moon">
      <div class="ball-container">
        <div class="ball">
          <div class="ball-line"></div>
          <div class="ball-line"></div>
          <div class="ball-line"></div>
          <div class="ball-line"></div>
        </div>
        <div class="ball-light"></div>
      </div>
    </div>
  </div>
</div>
/* 这一层是打消父元素 earth,旋转动画带来的影响 */
.moon-container {
  width: 400px;
  height: 400px;
  position: absolute;
  left: 50%;
  margin-left: -200px;
  top: -200px;
  border-radius: 50%;
  animation: moonTrack 20s linear infinite;
}
/* 画出轨迹,并旋转 */
.moon {
  width: 100%;
  height: 100%;
  border: solid 0.5px #ffffff;
  box-shadow: 0 0 22px #fff;
  border-radius: 50%;
  position: absolute;
  left: 0;
  top: 0;

  animation: rotateTrack 4s linear infinite;
  transform-style: preserve-3d;
}
/* 打消轨迹静止影响并且设置更快的旋转速度 */
.moon .ball-container {
  width: 50px;
  height: 50px;
  top: -25px;
  margin-left: -25px;
  animation: rotateContainer 4s linear infinite;
}
/* 自转动画调快一些 */
.moon .ball {
  width: 50px;
  height: 50px;
  animation: rotateSelf 5s infinite linear;
}

.moon .ball-light {
  background-image: linear-gradient(
    -20deg,
    #ddd6f3 0%,
    #faaca8 100%,
    #faaca8 100%
  );
  box-shadow: 0 0 1000px #ddd6f3;
}

.moon .ball-line {border-color: #ddd6f3;}

结语

月深了,鸟儿都早早睡了,祝大家中秋节开森高兴,晚安,接下来打算再写一篇 玉兔奔月的 3D 实现文章,心愿大家喜爱。

参考

  1. 【中秋】纯 CSS 实现日地月的公转
  1. 突变色彩
  2. 带你玩转 css3 的 3D!
退出移动版