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

  • A+
所属分类:Web前端
摘要

 

搭建舞台

<!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属性,计算每一个块元素的位置组成一个数字。

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

添加数字变换动画

...       .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修改自定义属性的值。

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

加入时间

...        .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获取当前时间,依次修改自定义变量的值。

 

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