使用css3画饼图

CSS3 Gradient介绍参考地址:

http://www.cnblogs.com/lhb25/archive/2013/01/30/css3-linear-gradient.html

http://www.zhangxinxu.com/wordpress/?p=3639

 

效果图:

 

 

 

html:

<div class="colorWheel">
    <div class="piece"></div>
</div>

css:

.colorWheel {
  position: relative;
  width: 16em;
  height: 16em;
  background: linear-gradient(36deg, #7c1 42%, transparent 42%),linear-gradient(72deg, #999 75.48%, transparent 75.48% ),linear-gradient(-36deg, #479bf6 42%, transparent 42%) 100% 0,linear-gradient(-72deg, yellow 75.48%, transparent 75.48%) 100% 0,linear-gradient(-36deg, transparent 58%, #643 58%) 0 100%,linear-gradient(-72deg, transparent 24.52%, #8a1 24.52%) 0 100%,linear-gradient(36deg, transparent 58%, #90a 42%) 100% 100%,linear-gradient(72deg,transparent 24.52%, #099 24.52%) 100% 100%,#43a1cd linear-gradient(#ba3e2e, #ba3e2e) 50% 0;
  background-repeat: no-repeat;
  background-size: 50% 50%;
  border:1px solid #ccc;
  border-radius: 50%;
  margin: 30px;
}
.piece{
  position: absolute;
  left: 8%;
  top: -2.6%;
  width: 100%;
  height: 100%;
  background: linear-gradient(-36deg, #5454E3 42%, transparent 42%) 100% 0;
  background-repeat: no-repeat;
  background-size: 50% 50%;
  border-radius: 50%;
}

  


多次对background设置linear-gradient值,已看晕。。。
那些角度和百分比究竟如何设置?
那块饼又是怎么被分出去的?
请看以下分析:
 
以背景中第一条liear-gradient设置为例:
background:linear-gradient(36deg,#ff0 42%, transparent 42% );
效果图如下:

  

第一个参数为角度,如图中将圆分为10等分,那么角度为360/10=36°,“度”用deg表示。
为了出现颜色骤停的直线而不是渐变色,在颜色过渡位置使用了属性值transparent。
百分比计算的是颜色所占整个区域的面积,计算公式为:100*sin36/(sqrt(2)*cos9)
     sin36 中的36指每个色块的占圆心角角度为36°;
     cos9 中的9用45-36计算得来。
如果每个色块中圆心角的度数为α, 计算面积公式转化为 100*sinα/(sqrt(2)*cos(45-α))

公式来源:

与梯度垂直的线上的所有点的颜色。从第三象限的顶点引出的垂直与梯度的直线是0% line,从第一象限的顶点引出的垂直线是100% line。画一条经过原点、且与0% line和100% line垂直的直线,与0% line交点为S,与100% line交点为E,在长方形内任取一点P,假设这点在颜色变化的分界线上,从点P做一条垂直于直线SE的线,垂点为I;线段SI和SE的比值为P点所在分界线分开的面积占整个面积的比例。
 
 
更直观的线条图,为了画圆截取的是正方形空间,有木有很熟悉的感觉。。。
连接AB点,过点A作垂直于PI的直线交于D点,则AD长度等于IS长度。
设正方形边长为a,则OB长度为a*sqrt(2)/2;
由数学知识可得,∠MOE=36°,∠EOB=9°;则OE=cos9*a*sqrt(2)/2;
另,IS=AD=sin36*a;
则:IS/SB=IS/2OE=sin36/(cos9*sqrt(2));

以P为顶点,角度为α的形成的面积占正方形总面积的比例计算公式为:100*sinα/(sqrt(2)*cos(45-α))
说了这么一大堆,原来只用这个公式来计算就可以了呢。
 
再来一个例子验证一下,将圆分为6等分:
每个色块角度为:360/6=60,
每个色块占所在正方形的面积比例为:100*sin60/(sqrt(2)*cos(45-60)),强大的js已经有这些常用数学公式的算法,Math.sin()和Math.cos()的参数均为弧度,将角度转化为弧度公式:弧度=角度*Π/180,代入上面公式,在浏览器调试面板中输入计算, 100*Math.sin(60*Math.PI/180)/(Math.sqrt(2)*Math.cos(-15*Math.PI/180))=63.4;

html:

<div class="sixWheel"></div>

css:

.sixWheel{
  width:12rem;
  height:12rem;
  margin-left: 50px;
  background: linear-gradient(60deg, #93f 63.4%, transparent 63.4%), linear-gradient(-60deg, #3f9 63.4%, transparent 63.4%) 100% 0, linear-gradient(-60deg, transparent 36.6%, #f63 36.6%) 0 100%, linear-gradient(60deg, transparent 36.6%, #69c 36.6%, #69c) 100% 100%, #ff9 linear-gradient(#39f, #39f) 50% 0;
  background-repeat: no-repeat;
  background-size: 50% 50%;
  border-radius: 50%;
}

效果图:

  

至此,饼已画完。
 
那切出来的一块又该怎么写呢?
 
见第一个栗子中的.piece元素,让这个元素和其父级元素.colorWheel有相同大小,只给这个元素中需要分出来的部分设置背景色,设置方法同上。控制.piece的位置,可实现被切分出去效果。
怎样移动位置才能使被切分的块与两侧的块距离相同是重点。要求的是下图中OA(横向移动距离)和AC(纵向移动距离)的长度。

  

如图示,假设OM和ON围成锐角为原区域,CE和CF围成的锐角为移动后区域,因为CE到OM的距离等于CF到ON的距离,过C点,作垂直于OM的直线交点为B点,作垂直与ON的直线交点为A点,则CB=CA。由此得出∠BOC=∠COA。
若∠AOB=36°,则∠AOC=18°。AC/OA=tan∠AOC。
 
所以,.piece横向移动位置和纵向移动位置的比例为tan(α/2)。

 

文章是由看了文章Dig Deep Into CSS Linear Gradients引出的, 文中部分图片来自此文中图片,强烈推荐看原文!!!

 

posted @ 2015-11-24 13:34  -nothing-  阅读(7494)  评论(0编辑  收藏  举报