搭建舞台
<!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;
}
.preserve {
transform-style: preserve-3d;
perspective: 1000px;
}
.container {
position: relative;
margin-top: 10vh;
text-align: center;
}
.stage {
transform: rotateX(10deg) rotateZ(0);
}
.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 = "0";
let b = "0";
if (String(timeTem.getHours()).length > 1) {
a = String(timeTem.getHours()).substring(0, 1);
b = String(timeTem.getHours()).substring(1, 2);
} else {
a = "0";
b = String(timeTem.getHours()).substring(0, 1);
}
let c = "0";
let d = "0";
if (String(timeTem.getMinutes()).length > 1) {
c = String(timeTem.getMinutes()).substring(0, 1);
d = String(timeTem.getMinutes()).substring(1, 2);
} else {
c = "0";
d = String(timeTem.getMinutes()).substring(0, 1);
}
let e = "0";
let f = "0";
if (String(timeTem.getSeconds()).length > 1) {
e = String(timeTem.getSeconds()).substring(0, 1);
f = String(timeTem.getSeconds()).substring(1, 2);
} else {
e = "0";
f = String(timeTem.getSeconds()).substring(0, 1);
}
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获取当前时间,依次修改自定义变量的值。
