移动APP里有个套餐余量的页面,设计师通常喜欢把剩余套餐或流量的进度做成一个圆的形状,里面再加上波浪。
纳尼?还要波浪??
~来来来,给你波浪。。。就是这样子的:
话说,写文章真的很费神,此篇不详细分析实现细节,主要思路全部在后面的SCSS注释信息里。
DOM
创建页面结构:
<ul class="wave-progress">
<li class="wave-blue">
<div class="wave" style="bottom: 95%;"></div>
<p class="text" data-text="95%">95%</p>
</li>
<li class="wave-orange">
<div class="wave" style="bottom: 70%;"></div>
<p class="text" data-text="70%">70%</p>
</li>
<li class="wave-purple">
<div class="wave" style="bottom: 45%;"></div>
<p class="text" data-text="45%">45%</p>
</li>
<li class="wave-cyan">
<div class="wave" style="bottom: 20%;"></div>
<p class="text" data-text="20%">20%</p>
</li>
</ul>
SCSS
这个CSDN的代码块不支持SCSS有点不友好,高亮提示注释提示颜色都不对。只能伪装成CSS文件,不过,也可以看清楚,影响不大。
@charset "UTF-8";
/* 波纹进度 */
// 进度圆大小
$progress-height: 160px !default;
// 文字大小
$progress-font: 36px !default;
// 进度颜色
$progress-colors: (
blue: #33A0FF,
orange: #FF744A,
purple: #8350D8,
cyan: #19C9CB
) !default;
// 进度圆容器
.wave-progress {
margin: 0;
padding: 0;
font-size: 0;
// 进度圆单元
> li {
display: inline-block;
list-style: none;
width: $progress-height;
height: $progress-height;
border-radius: 50%;
position: relative;
overflow: hidden;
// 为方便示例演示,添加单元间距
margin: 15px;
}
}
// 波纹
.wave {
position: absolute;
width: 100%;
height: 100%;
// 用伪元素绘制两个波纹容器
&::before,
&::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
z-index: 10;
// 设置大小合适的圆形容器(足够覆盖整个进度圆)
width: 800px;
height: 800px;
border-radius: 45%;
// 一定透明度的白色背景色
background-color: rgba(255, 255, 255, .8);
// 挪到合适的位置
transform: translateX(-50%) rotate(0);
// 添加旋转动画
animation: rotate 6s linear infinite;
}
// 通过重置一个波纹的圆角大小、动画执行时间、延迟间隔
// 来制造波纹动画的视觉差和时间差
&::after {
border-radius: 48%;
transform: translateX(-50%) rotate(0);
animation: rotate 10s linear -5s infinite;
z-index: 20;
}
}
// 进度值
.text {
position: absolute;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
z-index: 30;
text-align: center;
font-size: $progress-font;
font-weight: 900;
line-height: $progress-height;
color: white;
// 文字重叠描边,进度值较小场景下白色文字与背景的区分
&::before {
// 使用函数取值,DOM 中这个属性必须有值,而且需要与进度值保值一致
content: attr(data-text);
position: absolute;
-webkit-text-stroke: 1px orange;
z-index: 20;
}
}
// 旋转动画
@keyframes rotate {
50% {
transform: translateX(-50%) rotate(180deg);
}
100% {
transform: translateX(-50%) rotate(360deg);
}
}
// 枚举进度颜色
@each $key, $value in $progress-colors {
.wave-#{$key} {
background-color: $value;
// 文字描边颜色与背景一致
.text::before {
-webkit-text-stroke: 1px $value;
}
}
}