实现 3D 时间动画展示效果

搭建舞台

<!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 type="text/css">
      html,      body {        width: 100%;        height: 100%;        background-color: #000;        overflow: hidden;
      }      /* 设置视距1000px 子元素在3D中变换  */      .preserve {        transform-style: preserve-3d;        perspective: 1000px;
      }      /* 容器 */      .container {        position: relative;        margin-top: 10vh;        text-align: center;        /* animation: rotateReverse 10s infinite linear; */
      }      /* 舞台 */      .stage {        transform: rotateX(10deg) rotateZ(0);        /* animation: rotate 10s infinite linear; */
      }      /* 数字样式  */      .number {        position: relative;        width: 3vw;        height: 12vw;        display: inline-block;        margin: 3vw 3vw 0 0;
      }      .line {        position: absolute;        top: 0;        left: 0;        width: 3vw;        height: 2px;        background: #181919;
      }      .line::before,      .line::after {        content: "";        position: absolute;        top: 0;        width: 50%;        height: 100%;        background-color: #34eabc;        box-shadow: 0 0 1vw #0bfdfd, inset 0 0 0.125vmin #0bfdfd;
      }      .line::before {        left: 0;        transition: all 0.5s ease-in;
      }      .line::after {        right: 0;        transition: all 0.5s ease-out;
      }      /* 计算每根线的位置 */      .line:nth-child(1) {        top: -0.2vw;
      }      .line:nth-child(2) {        top: 3.2vw;
      }      .line:nth-child(3) {        top: 6.6vw;
      }      .line:nth-child(4) {        transform: rotate(90deg) translateY(0.2vw);        /* 设置 旋转中心为 最左边 元素中点  */        transform-origin: 0 center;
      }      .line:nth-child(5) {        transform: rotate(-90deg) translateY(0.2vw);        /* 设置 旋转中心为 最右边 元素中点  */        transform-origin: 100% center;
      }      .line:nth-child(6) {        top: 3.4vw;        transform: rotate(90deg) translateY(0.2vw);        transform-origin: 0 center;
      }      .line:nth-child(7) {        top: 3.4vw;        transform: rotate(-90deg) translateY(0.2vw);        transform-origin: 100% center;
      }      /* 减少我们的距离 实现阴影效果 */      .translate::before,      .translate::after {        transform: translateZ(50px);
      }    </style>  </head>  <body>    <div class="container preserve">      <div class="stage preserve">        <div class="number preserve">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>      </div>    </div>  </body></html>复制代码
  • 确认组成数字需要多少个块元素

  • 使用伪元素和元素的颜色差,让伪元素向我们的方向移动,实现影子效果。

  • 使用transform属性,计算每一个块元素的位置组成一个数字。

添加数字变换动画

...      .number[data-digit="1"] .line:nth-child(1)::before,      .number[data-digit="1"] .line:nth-child(1)::after,      .number[data-digit="1"] .line:nth-child(2)::before,      .number[data-digit="1"] .line:nth-child(2)::after,      .number[data-digit="1"] .line:nth-child(3)::before,      .number[data-digit="1"] .line:nth-child(3)::after,      .number[data-digit="1"] .line:nth-child(4)::before,      .number[data-digit="1"] .line:nth-child(4)::after,      .number[data-digit="1"] .line:nth-child(6)::before,      .number[data-digit="1"] .line:nth-child(6)::after,      .number[data-digit="2"] .line:nth-child(4)::before,      .number[data-digit="2"] .line:nth-child(4)::after,      .number[data-digit="2"] .line:nth-child(7)::before,      .number[data-digit="2"] .line:nth-child(7)::after,      .number[data-digit="3"] .line:nth-child(4)::before,      .number[data-digit="3"] .line:nth-child(4)::after,      .number[data-digit="3"] .line:nth-child(6)::before,      .number[data-digit="3"] .line:nth-child(6)::after,      .number[data-digit="4"] .line:nth-child(1)::before,      .number[data-digit="4"] .line:nth-child(1)::after,      .number[data-digit="4"] .line:nth-child(3)::before,      .number[data-digit="4"] .line:nth-child(3)::after,      .number[data-digit="4"] .line:nth-child(6)::before,      .number[data-digit="4"] .line:nth-child(6)::after,      .number[data-digit="5"] .line:nth-child(5)::before,      .number[data-digit="5"] .line:nth-child(5)::after,      .number[data-digit="5"] .line:nth-child(6)::before,      .number[data-digit="5"] .line:nth-child(6)::after,      .number[data-digit="6"] .line:nth-child(5)::before,      .number[data-digit="6"] .line:nth-child(5)::after,      .number[data-digit="7"] .line:nth-child(2)::before,      .number[data-digit="7"] .line:nth-child(2)::after,      .number[data-digit="7"] .line:nth-child(3)::before,      .number[data-digit="7"] .line:nth-child(3)::after,      .number[data-digit="7"] .line:nth-child(4)::before,      .number[data-digit="7"] .line:nth-child(4)::after,      .number[data-digit="7"] .line:nth-child(6)::before,      .number[data-digit="7"] .line:nth-child(6)::after,
      .number[data-digit="9"] .line:nth-child(6)::before,      .number[data-digit="9"] .line:nth-child(6)::after,
      .number[data-digit="0"] .line:nth-child(2)::before,      .number[data-digit="0"] .line:nth-child(2)::after {        transform: translateZ(25px);        background: #3c4444;        box-shadow: 0 0 1vw #425454;
      }
 ...

    <script type="text/javascript">
      (function () {
        let numbers = document.getElementsByClassName("number")
        setInterval(() => {
          Array.prototype.slice.call(numbers).forEach((key) => {
            key.setAttribute("data-digit",parseInt(Math.random() * 9));
          });
        }, 1000);
      })()
    </script>
...复制代码
  • 使用transition属性line::before和line::after设置过度动画。

  • 通过css属性选择器,获取自定义属性的值。通过变换的值来设置在不同数字下,哪些块需要改变。

  • 使用js修改自定义属性的值。

加入时间

...

      .colon{
        position: relative;
        display: inline-block;
        width: 2vw;
        height: 12vw;
        margin: 1vw 2vw 0 0;
        animation:colonFra 1s linear infinite ;
      }
      .colon::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 1vw;
        height: 1vw;
        background-color: #34eabc;
        border-radius: 50%;
      }
      .colon::after {
        content: "";
        position: absolute;
        top: 4vw;
        left: 0;
        width: 1vw;
        height: 1vw;
        background-color: #34eabc;
        border-radius: 50%;
      }
      .colonS{
        left: -1.3vw;
      }
      .colonF{
        left: 1vw;
      }
      @keyframes colonFra {
        0% {
          opacity: 0;
        }
        100% {
          opacity: 1;
        }
      }
...        <div class="number preserve" data-digit="0">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>        <div class="colon preserve colonS"></div>        <div class="number preserve" data-digit="0">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>        <div class="number preserve" data-digit="0">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>        <div class="colon preserve colonF"></div>        <div class="number preserve" data-digit="0">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>        <div class="number preserve" data-digit="0">          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>          <div class="line preserve translate"></div>        </div>
...    <script type="text/javascript">
      function time(){        let timeTem = new Date();        let a = timeTem.getHours().toString().substring(0,1);        let b = timeTem.getHours().length > 1 ? 0 : timeTem.getHours().toString().substring(1,2);        let c = timeTem.getMinutes().toString().substring(0,1);        let d = timeTem.getMinutes().length > 1 ? 0 : timeTem.getMinutes().toString().substring(1,2);        let e = timeTem.getSeconds().toString().substring(0,1);        let f = timeTem.getSeconds().length > 1 ? 0 : timeTem.getSeconds().toString().substring(1,2);        return [a,b,c,d,e,f]
      }
      (function () {        let numbers = document.getElementsByClassName("number")        setInterval(() => {          let arr = time();          Array.prototype.slice.call(numbers).forEach((key,index) => {
            key.setAttribute("data-digit",arr[index]);
          });
        }, 1000);
      })()    </script>复制代码
  • 先定义时分秒钟的,间隔。

  • 使用js获取当前时间,依次修改自定义变量的值。

本文首发于前端黑洞网,博客园同步跟新

(0)

相关推荐