来自CSS3的黑科技--如何实现环形进度条

CSS3的提出使得CSS不再是单纯的样式表,只要运用得到,就可以实现一些我们很棒的动画效果,最近项目有需求需要实现一个环形进度条,一开始没有思路,在看了《CSS Secret》之后觉得有受启发,便记录下这个过程。在过去,实现一个这样的进度条难免要拼接大量图片,CSS3和HTML5的出现使得这个过程变得简单无比。
首先,我们需要一个元素来承载我们的样式:

1
<div class="pie"></div>

事实上,如果要实现环形图,只要实现饼图,然后在其上覆盖一层遮罩即可,所以我们可以先从如何实现饼图开始:

1
2
3
4
5
6
7
8
.pie {
width : 200px;
height : 200px;
border-radius: 50%;
background: #ddd;
margin: 0 auto;
position: relative;
}

我们首先通过.pie实现了一个圆形,并将其居中方便我们进行观察,效果如下:

我们需要用蓝色来代表饼图的比例,《CSS Secret》给出的思路是覆盖一层与背景同色的伪元素上去,使其旋转露出比例的部分,那么首先,需要将圆形另一半的背景色置为蓝色,可以通过线性渐变来实现:

1
background-image: linear-gradient(to right, transparent 50%, #3195d0 0);

效果如下:

然后,我们通过伪元素::before添加一层遮罩,使其遮挡住右半部分:

1
2
3
4
5
6
7
8
.pie::before {
content: '';
display: block;
margin-left: 50%;
height: 100%;
background-color: inherit;
border-radius: 0 100% 100% 0 / 50%;

伪元素的宽度为圆的一半,并位于右边遮挡住右半部分,当然,仅仅是这样还不够,这里的关键是设置border-radius使其呈现半圆形,border-radius通过/分隔四个角的水平半径和垂直半径。
这时候,我们通过transform可以使伪元素发生旋转,露出想要的比例:

1
2
transform-origin: left;
transform: rotate(.1turn);

效果如下:

已经离我们想要的越来越接近了,为了让饼图可以动起来,我们可以通过CSS3的animation来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@keyframes spin {
to {
transform: rotate(.5turn);
}
}
@keyframes bg {
50% {
background: #3195d0;
}
}
.pie::before {
content: '';
display: block;
margin-left: 50%;
height: 100%;
background-color: inherit;
border-radius: 0 100% 100% 0 / 50%;
transform-origin: left;
transform: rotate(.1turn);
animation: spin 10s linear infinite,
bg 20s step-end infinite;
}

注意,@keyframes bg的作用是当饼图旋转到一半时应该更换背景颜色,才能达到我们想要的效果,最后,我们再通过::after添加一层伪元素,使圆环看上去有空心的效果:

1
2
3
4
5
6
7
8
9
10
11
12
.pie::after {
content: '';
display: block;
height: 80%;
width: 80%;
position: absolute;
z-index: 1;
top: 10%;
left: 10%;
background-color: #fff;
border-radius: 50%;
}

最后的效果如下:

如此就实现了一个简单的圆环,当然,你可以配合JS来添加一些交互,在这里安利一波《CSS Secret》,充满着CSS3黑科技的好书,据说中文版目前还没有人在翻译。