简介
通过伪类和关键帧动画实现地铁车辆侧面图
在线演示
伪元素和关键帧动画
实现代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta content="always" name="referrer">
<meta name="theme-color" content="#ffffff">
<meta name="description" content="">
<title>伪元素和关键帧动画</title>
<style>
.loading{
--ballSize: 10px;
--containerSize: 150px;
--duration: 2s;
--barderWidth: 3px;
width: var(--containerSize);
height: var(--containerSize);
border: 1px solid #12332100;
margin: 50px auto;
position: relative;
border-radius:50%;
}
.loading:before{
content: '';
position: absolute;
left: calc( 50% - var(--ballSize) / 2 - var(--barderWidth) );
top: calc( 40% - var(--ballSize) / 2 - var(--barderWidth) );
width: var(--ballSize);
height: var(--ballSize);
border-radius: 50%;
background: transparent;
border-top: 0 solid gray;
border-left: var(--barderWidth) solid gray;
border-right: var(--barderWidth) solid gray;
border-bottom: 0 solid gray;
animation: run 3s ease-in infinite;
}
.loading:after{
content: '';
position: absolute;
left: calc( 50% - var(--ballSize) / 2 - var(--barderWidth) / 10 );
top: calc( 50% - var(--ballSize) / 2 - 4*var(--barderWidth) );
width: calc( var(--ballSize) / 2 );
height: calc( var(--ballSize) / 2 );
border-radius: 50%;
background: transparent;
border-top: 0 solid gray;
border-left: var(--barderWidth) solid gray;
border-right: var(--barderWidth) solid gray;
border-bottom: 0 solid gray;
animation: run 2s ease-out infinite;
}
@keyframes run {
0%{
border-color: #00ff0022;
}
25%{
border-color: #00ff0044;
}
50%{
border-color: #00ff0088;
}
75%{
border-color: #00ff00aa;
}
100%{
border-color: #00ff00;
}
}
.dot{
position: absolute;
left: 50%;
top: 0;
width: var(--ballSize);
height: var(--ballSize);
margin-left: calc( var(--ballSize) / (-2) );
margin-top: calc( var(--ballSize) / (-2) );
background: #65432123;
transform-origin: center calc( var(--containerSize) / 2 + var(--ballSize) / 2 );
perspective: 70px;
transform-style: preserve-3d;
}
.dot:nth-child(1){
transform: rotate(0deg);
}
.dot:nth-child(1)::before,.dot:nth-child(1)::after{
animation-delay: calc( var(--duration) / 36 * ( 1 - 1)*6*-1 );
}
.dot:nth-child(2){
transform: rotate(10deg);
}
.dot:nth-child(2)::before,.dot:nth-child(2)::after{
animation-delay: calc( var(--duration) / 36 * ( 2 - 1 )*6*-1 );
}
.dot:nth-child(3){
transform: rotate(20deg);
}
.dot:nth-child(3)::before,.dot:nth-child(3)::after{
animation-delay: calc( var(--duration) / 36 * ( 3 - 1 )*6*-1 );
}
.dot:nth-child(4){
transform: rotate(30deg);
}
.dot:nth-child(4)::before,.dot:nth-child(4)::after{
animation-delay: calc( var(--duration) / 36 * ( 4 - 1 )*6*-1 );
}
.dot:nth-child(5){
transform: rotate(40deg);
}
.dot:nth-child(5)::before,.dot:nth-child(5)::after{
animation-delay: calc( var(--duration) / 36 * ( 5 - 1 )*6*-1 );
}
.dot:nth-child(6){
transform: rotate(50deg);
}
.dot:nth-child(6)::before,.dot:nth-child(6)::after{
animation-delay: calc( var(--duration) / 36 * ( 6 - 1 )*6*-1 );
}
.dot:nth-child(7){
transform: rotate(60deg);
}
.dot:nth-child(7)::before,.dot:nth-child(7)::after{
animation-delay: calc( var(--duration) / 36 * ( 7 - 1 )*6*-1 );
}
.dot:nth-child(8){
transform: rotate(70deg);
}
.dot:nth-child(8)::before,.dot:nth-child(8)::after{
animation-delay: calc( var(--duration) / 36 * ( 8 - 1 )*6*-1 );
}
.dot:nth-child(9){
transform: rotate(80deg);
}
.dot:nth-child(9)::before,.dot:nth-child(9)::after{
animation-delay: calc( var(--duration) / 36 * ( 9 - 1 )*6*-1 );
}
.dot:nth-child(10){
transform: rotate(90deg);
}
.dot:nth-child(10)::before,.dot:nth-child(10)::after{
animation-delay: calc( var(--duration) / 36 * ( 10 - 1 )*6*-1 );
}
.dot:nth-child(11){
transform: rotate(100deg);
}
.dot:nth-child(11)::before,.dot:nth-child(11)::after{
animation-delay: calc( var(--duration) / 36 * ( 11 - 1 )*6*-1 );
}
.dot:nth-child(12){
transform: rotate(110deg);
}
.dot:nth-child(12)::before,.dot:nth-child(12)::after{
animation-delay: calc( var(--duration) / 36 * ( 12 - 1 )*6*-1 );
}
.dot:nth-child(13){
transform: rotate(120deg);
}
.dot:nth-child(13)::before,.dot:nth-child(13)::after{
animation-delay: calc( var(--duration) / 36 * ( 13 - 1 )*6*-1 );
}
.dot:nth-child(14){
transform: rotate(130deg);
}
.dot:nth-child(14)::before,.dot:nth-child(14)::after{
animation-delay: calc( var(--duration) / 36 * ( 14 - 1 )*6*-1 );
}
.dot:nth-child(15){
transform: rotate(140deg);
}
.dot:nth-child(15)::before,.dot:nth-child(15)::after{
animation-delay: calc( var(--duration) / 36 * ( 15 - 1 )*6*-1 );
}
.dot:nth-child(16){
transform: rotate(150deg);
}
.dot:nth-child(16)::before,.dot:nth-child(16)::after{
animation-delay: calc( var(--duration) / 36 * ( 16 - 1 )*6*-1 );
}
.dot:nth-child(17){
transform: rotate(160deg);
}
.dot:nth-child(17)::before,.dot:nth-child(17)::after{
animation-delay: calc( var(--duration) / 36 * ( 17 - 1 )*6*-1 );
}
.dot:nth-child(18){
transform: rotate(170deg);
}
.dot:nth-child(18)::before,.dot:nth-child(18)::after{
animation-delay: calc( var(--duration) / 36 * ( 18 - 1 )*6*-1 );
}
.dot:nth-child(19){
transform: rotate(180deg);
}
.dot:nth-child(19)::before,.dot:nth-child(19)::after{
animation-delay: calc( var(--duration) / 36 * ( 19 - 1 )*6*-1 );
}
.dot:nth-child(20){
transform: rotate(190deg);
}
.dot:nth-child(20)::before,.dot:nth-child(20)::after{
animation-delay: calc( var(--duration) / 36 * ( 20 - 1 )*6*-1 );
}
.dot:nth-child(21){
transform: rotate(200deg);
}
.dot:nth-child(21)::before,.dot:nth-child(21)::after{
animation-delay: calc( var(--duration) / 36 * ( 21 - 1 )*6*-1 );
}
.dot:nth-child(22){
transform: rotate(210deg);
}
.dot:nth-child(22)::before,.dot:nth-child(22)::after{
animation-delay: calc( var(--duration) / 36 * ( 22 - 1 )*6*-1 );
}
.dot:nth-child(23){
transform: rotate(220deg);
}
.dot:nth-child(23)::before,.dot:nth-child(23)::after{
animation-delay: calc( var(--duration) / 36 * ( 23 - 1 )*6*-1 );
}
.dot:nth-child(24){
transform: rotate(230deg);
}
.dot:nth-child(24)::before,.dot:nth-child(24)::after{
animation-delay: calc( var(--duration) / 36 * ( 24 - 1 )*6*-1 );
}
.dot:nth-child(25){
transform: rotate(240deg);
}
.dot:nth-child(25)::before,.dot:nth-child(25)::after{
animation-delay: calc( var(--duration) / 36 * ( 25 - 1 )*6*-1 );
}
.dot:nth-child(26){
transform: rotate(250deg);
}
.dot:nth-child(26)::before,.dot:nth-child(26)::after{
animation-delay: calc( var(--duration) / 36 * ( 26 - 1 )*6*-1 );
}
.dot:nth-child(27){
transform: rotate(260deg);
}
.dot:nth-child(27)::before,.dot:nth-child(27)::after{
animation-delay: calc( var(--duration) / 36 * ( 27 - 1 )*6*-1 );
}
.dot:nth-child(28){
transform: rotate(270deg);
}
.dot:nth-child(28)::before,.dot:nth-child(28)::after{
animation-delay: calc( var(--duration) / 36 * ( 28 - 1 )*6*-1 );
}
.dot:nth-child(29){
transform: rotate(280deg);
}
.dot:nth-child(29)::before,.dot:nth-child(29)::after{
animation-delay: calc( var(--duration) / 36 * ( 29 - 1 )*6*-1 );
}
.dot:nth-child(30){
transform: rotate(290deg);
}
.dot:nth-child(30)::before,.dot:nth-child(30)::after{
animation-delay: calc( var(--duration) / 36 * ( 30 - 1 )*6*-1 );
}
.dot:nth-child(31){
transform: rotate(300deg);
}
.dot:nth-child(31)::before,.dot:nth-child(31)::after{
animation-delay: calc( var(--duration) / 36 * ( 31 - 1 )*6*-1 );
}
.dot:nth-child(32){
transform: rotate(310deg);
}
.dot:nth-child(32)::before,.dot:nth-child(32)::after{
animation-delay: calc( var(--duration) / 36 * ( 32 - 1 )*6*-1 );
}
.dot:nth-child(33){
transform: rotate(320deg);
}
.dot:nth-child(33)::before,.dot:nth-child(33)::after{
animation-delay: calc( var(--duration) / 36 * ( 33 - 1 )*6*-1 );
}
.dot:nth-child(34){
transform: rotate(330deg);
}
.dot:nth-child(34)::before,.dot:nth-child(34)::after{
animation-delay: calc( var(--duration) / 36 * ( 34 - 1 )*6*-1 );
}
.dot:nth-child(35){
transform: rotate(340deg);
}
.dot:nth-child(35)::before,.dot:nth-child(35)::after{
animation-delay: calc( var(--duration) / 36 * ( 35 - 1 )*6*-1 );
}
.dot:nth-child(36){
transform: rotate(350deg);
}
.dot:nth-child(36)::before,.dot:nth-child(36)::after{
animation-delay: calc( var(--duration) / 36 * ( 36 - 1 )*6*-1 );
}
.dot::before,.dot::after{
content: '';
position: absolute;
left: 0;
top: 0;
width: var(--ballSize);
height: var(--ballSize);
border-radius: 50%;
}
.dot::before{
background: #123456;
top: -100%;
animation: rotate-black var(--duration) infinite;
}
@keyframes rotate-black{
0%{
animation-timing-function: ease-in;
}
25%{
transform: translate3d(0,100%,10px);
animation-timing-function: ease-out;
}
50%{
transform: translate3d(0,200%,0);
animation-timing-function: ease-in;
}
75%{
transform: translate3d(0,100%,-10px);
animation-timing-function: ease-out;
}
}
.dot::after{
background: red;
top: 100%;
animation: rotate-red var(--duration) infinite;
}
@keyframes rotate-red{
0%{
animation-timing-function: ease-in;
}
25%{
transform: translate3d(0,-100%,-10px);
animation-timing-function: ease-out;
}
50%{
transform: translate3d(0,-200%,0);
animation-timing-function: ease-in;
}
75%{
transform: translate3d(0,-100%,10px);
animation-timing-function: ease-out;
}
}
.train {
--speed: 1s;
display: black;
align-items: center;
box-sizing: border-box;
flex: 1;
height: 100px;
padding: 0 60px;
padding-top: 20px;
flex-wrap: wrap;
}
.content_item {
display: flex;
align-items: center;
justify-content: space-between;
flex: 1;
padding: 0 8px;
}
.carriageUp {
background: #eaeaeb;
box-shadow: 0px 20px 20px 5px #01071788;
height: 100%;
display: flex;
align-items: center;
justify-content: space-around;
color: #a2a7b5;
font-size: 14px;
font-weight: bold;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
width: calc( ( 100% - (8 - 1) * 8px) / 8);
cursor: pointer;
}
.carriageUp::before{
content: "";
position: relative;
z-index: 1;
width: 40px;
height: 20px;
border-radius: 2px;
background-color: #dbdbe6;
box-shadow: 1px -1px 1px 1px #0000004d;
top: 0px;
left: 0px;
}
.carriageUp::after{
content: "";
position: relative;
z-index: 1;
width: 40px;
height: 20px;
border-radius: 2px;
background-color: #dbdbe6;
box-shadow: 1px -1px 1px 1px #0000004d;
top: 0px;
right: 0px;
}
.carriageUp:first-child{
border-top-left-radius: 80px;
}
.carriageUp:last-child{
border-top-right-radius: 80px;
}
.carriageUp:first-child::before{
left: -5px;
border-top-left-radius: 20px;
border-bottom-left-radius: 5px;
width: 40px;
}
.carriageUp.openmc1:first-child::before{
background: #4ebe11;
}
.carriageUp:last-child::after{
right: -5px;
border-top-right-radius: 20px;
border-bottom-right-radius: 5px;
width: 40px;
}
.carriageUp.openmc2:last-child::after{
background: #4ebe11;
}
.carriageDown {
background: #eaeaeb;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #a2a7b5;
font-size: 20px;
font-weight: bold;
border-radius: 1px;
border-top: 10px solid #dbdbe6;
width: calc( ( 100% - (8 - 1) * 8px) / 8);
}
.carriageDown::before{
content: "";
position: relative;
z-index: 1;
width: 40px;
height: 40px;
border-radius: 20px;
background-color: #dbdbe6;
box-shadow: 0px -1px 1px 1px #0000004f;
top: 0px;
left: -20px;
animation: runRight calc( var(--speed)/24 ) linear infinite;
}
.carriageDown::after{
content: "";
position: relative;
z-index: 1;
width: 40px;
height: 40px;
border-radius: 20px;
background-color: #dbdbe6;
box-shadow: 0px -1px 1px 1px #0000004f;
top: 0px;
right: -20px;
animation: runRight calc( var(--speed)/24 ) linear infinite;
}
.carriageDown:first-child{
border-bottom-left-radius: 80px;
}
.carriageDown:last-child{
border-bottom-right-radius: 80px;
}
.content_item:first-child{
height: 80%;
}
.content_item:last-child{
height: 20%;
}
@keyframes runRight{
0%{
transform: rotate(0deg) scale(0.96);
}
25%{
transform: rotate(-90deg) scale(0.98);
}
50%{
transform: rotate(-180deg) scale(1);
}
75%{
transform: rotate(-270deg) scale(0.98);
}
100%{
transform: rotate(-360deg) scale(0.96);
}
}
@keyframes runLeft{
0%{
transform: rotate(0deg) scale(0.96);
}
25%{
transform: rotate(90deg) scale(0.98);
}
50%{
transform: rotate(180deg) scale(1);
}
75%{
transform: rotate(270deg) scale(0.98);
}
100%{
transform: rotate(360deg) scale(0.96);
}
}
</style>
</head>
<body>
<div class="loading">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
<div class="train">
<div class="content_item">
<div class="carriageUp openmc1"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
<div class="carriageUp"></div>
</div>
<div class="content_item">
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
<div class="carriageDown"></div>
</div>
</div>
<div style="width: 100%;height: 30px;background:#123456;"></div>
<script>
</script>
</body>
</html>