实现 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)
