主题
Loading 效果
实现原理: 将两个小球设为一组, 交替循环, 然后重复改变旋转角度添加另一组, 最后形成完整环形。
scss
$ballSize: 12px; // 小球尺寸
$containerSize: 250px; // 容器尺寸
$n: 36;
$pdeg: 360deg / $n;
.kj_loading {
width: $containerSize;
height: $containerSize;
margin: 50px auto;
position: relative;
border-radius: 50%;
.kj_dot {
position: absolute;
left: 50%;
top: 50%;
width: $ballSize;
height: $ballSize;
margin-left: -$ballSize / 2;
margin-top: -$ballSize / 2;
perspective: 70px;
transform-style: preserve-3d;
&::before, &::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
}
&::before {
background: rgb(161, 240, 247);
top: -100%;
animation: moveBlack 2s infinite;
}
&::after {
background: rgb(135, 163, 247);
top: 100%;
animation: moveWhite 2s infinite;
}
}
}
@for $i from 1 through 36 {
.kj_dot:nth-child(#{$i}) {
transform: rotate($pdeg * $i) translateY(-$containerSize / 2);
&::before, &::after {
animation-delay: -2000s / $n * 6 * $i;
}
}
}
@keyframes moveBlack {
0% {
animation-timing-function: ease-in;
}
25% {
transform: translate3d(0, 100%, $ballSize);
animation-timing-function: ease-out;
}
50% {
transform: translate3d(0, 200%, 0);
animation-timing-function: ease-in;
}
75% {
transform: translate3d(0, 100%, -$ballSize);
animation-timing-function: ease-out;
}
}
@keyframes moveWhite {
0% {
animation-timing-function: ease-in;
}
25% {
transform: translate3d(0, -100%, -$ballSize);
animation-timing-function: ease-out;
}
50% {
transform: translate3d(0, -200%, 0);
animation-timing-function: ease-in;
}
75% {
transform: translate3d(0, -100%, $ballSize);
animation-timing-function: ease-out;
}
}
vue
<div class="kj_loading">
<!-- 重复添加 36 个 dot 元素 -->
<div class="kj_dot" v-for="(item, index) in 36" :key="index"></div>
</div>