[CSS揭秘]饼图全面解析

现在的网页设计中,饼图的运用极为普遍。如:简单的统计图表,进度指示器,定时器等等。饼图的技术实现方式也非常多,主要是使用JavaScript配合canvas来实现,从而诞生了一大批的图表绘制JS库。但是单纯使用CSS来实现饼图的技术还是在CSS3推出后才开始出现。

今天就来讲讲基于transform的CSS解决方案

实现原理是使用一个元素作为容器,其他部分由伪元素,变形属性和CSS渐变来实现。

先看一个简单的案例:

.pie{
100px;
height: 100px;
border-radius: 50%;
background-color: yellowgreen;
}

 

如何实现扇形呢?有一种思路就是将圆形分为左右两半,通过伪元素覆盖其中一半,再将伪元素通过旋转来决定露出多大的扇区。

.pie{
100px;
height: 100px;
border-radius: 50%;
background-color: yellowgreen;
background-image: linear-gradient(to right, transparent 50%, #655 0);
}
.pie::before{
content: "";
display: block;
margin-left: 50%;
height: 100%;
background-color: inherit; //继承父级元素.pie的颜色
border-radius: 0 100% 100% 0 / 50%; //将伪元素的右侧设置为一个半圆形
transform-origin: left;
}

 

接下来激动人心的时刻即将到来,通过旋转伪元素来实现不同大小的扇形图案。

旋转0.1turn(36deg) 10%

 

旋转0.2turn(72deg) 20%

 

旋转0.5turn(180deg) 50%

 

然而好景不长,当你旋转超过50°时就会发现杯具了。解决办法是什么呢,我们想到可以将伪元素的背景颜色设置为扇形区域颜色,这样旋转0.1到0.5turn区间时就会达到相应的50%到100%的扇形效果。

旋转0.1turn(36deg) 60%

 

旋转0.25turn(45deg) 75%

 

聪明的小伙伴们肯定想到了,这完全可以做成一个旋转动画效果呀。炫酷的进度指示器就这样实现了。

.pie4{
100px;
height: 100px;
border-radius: 50%;
background-color: yellowgreen;
background-image: linear-gradient(to right, transparent 50%, #655 0);
overflow: hidden;
}
.pie4::before{
content: "";
display: block;
margin-left: 50%;
height: 100%;
background-color: inherit;
border-radius: 0 100% 100% 0 / 50%;
transform-origin: left;
animation: spin 3s linear infinite,
bg 6s step-start infinite; // 这里的背景色替换刚好是每一次转完180度之后变换一次,所以背景色替换的动画时间是伪元素旋转动画时间的2倍
}
@keyframes spin{
to{
transform: rotate(180deg);
transform: rotate(0.5turn);
}
}
@keyframes bg{
50%{
background: #655;
}
}

 
接下来就是思考如何快速的制作多个不同比率的静态饼图了。解决方案是利用CSS动画中的延迟时间animation-delay属性。如果将这个值设置为负值,那么动画就会直接跳转到动画中的某一时刻。
一个负的延迟时间值是合法的,与0s的延迟类似,它意味着动画会立即开始播放,但是会自动前进到延迟时间的绝对值处,就好像动画在过去已经播放了指定的时间一样。因此实际效果就是动画跳过指定时间而从中间开始播放了。

因此一个合理的解决方案就是将动画时间设置为100s。这样如果想到实现20%的比率效果,只需要设置延迟时间为-20s即可。注意,这里的动画是永远处于暂停状态的,我们指定的延迟时间和动画总时间都不会产生任何副作用。最后一个问题就是在父元素上设置的延迟时间可以通过继承从而在伪元素上获取。

20%
60%
用JS来获取比率值从而动态设置animation-delay值
var pieNode = document.querySelectorAll(".pie");
for(var i = 0; i < pieNode.length; i++){
    var rate = parseFloat(pieNode[i].textContent);
    pieNode[i].style.animationDelay = '-'+rate+'s';
}

另外可以考虑将文字放在饼图中间并设置透明色从而隐藏文字,并且将伪元素通过绝对定位的方式覆盖到父级元素之上。

最后,推荐一篇张大神的博文《CSS3实现鸡蛋饼饼状图Loading等待转转转》

http://www.zhangxinxu.com/wordpress/2014/04/css3-pie-loading-waiting-animation/

原文地址:https://www.cnblogs.com/joyjoe/p/6922917.html