效果图:
代码:
<!doctype html>
<html lang="zh" class="no-js">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>svg饼图</title>
<style>
/* ProBars v1.1, Copyright 2014, Joe Mottershaw, https://github.com/joemottershaw/// =============================================================================== */.pro-bar-container{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;width:100%;height:15px;margin:0 0 20px;border:2px solid #222;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;background:#222;overflow:hidden}.pro-bar-container.color-turquoise{border-color:#1abc9c;background:#1abc9c}.pro-bar-container.color-green-sea{border-color:#16a085;background:#16a085}.pro-bar-container.color-emerald{border-color:#2ecc71;background:#2ecc71}.pro-bar-container.color-nephritis{border-color:#27ae60;background:#27ae60}.pro-bar-container.color-peter-river{border-color:#3498db;background:#3498db}.pro-bar-container.color-belize-hole{border-color:#2980b9;background:#2980b9}.pro-bar-container.color-amethyst{border-color:#9b59b6;background:#9b59b6}.pro-bar-container.color-wisteria{border-color:#8e44ad;background:#8e44ad}.pro-bar-container.color-wet-asphalt{border-color:#34495e;background:#34495e}.pro-bar-container.color-midnight-blue{border-color:#2c3e50;background:#2c3e50}.pro-bar-container.color-sun-flower{border-color:#f1c40f;background:#f1c40f}.pro-bar-container.color-orange{border-color:#f39c12;background:#f39c12}.pro-bar-container.color-carrot{border-color:#e67e22;background:#e67e22}.pro-bar-container.color-pumpkin{border-color:#d35400;background:#d35400}.pro-bar-container.color-alizarin{border-color:#e74c3c;background:#e74c3c}.pro-bar-container.color-pomegranate{border-color:#c0392b;background:#c0392b}.pro-bar-container.color-clouds{border-color:#ecf0f1;background:#ecf0f1}.pro-bar-container.color-silver{border-color:#bdc3c7;background:#bdc3c7}.pro-bar-container.color-concrete{border-color:#95a5a6;background:#95a5a6}.pro-bar-container.color-asbestos{border-color:#7f8c8d;background:#7f8c8d}.pro-bar{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;width:0;height:15px;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;background:#444}.pro-bar.bar-100{width:100%}.pro-bar.bar-99{width:99%}.pro-bar.bar-98{width:98%}.pro-bar.bar-97{width:97%}.pro-bar.bar-96{width:96%}.pro-bar.bar-95{width:95%}.pro-bar.bar-94{width:94%}.pro-bar.bar-93{width:93%}.pro-bar.bar-92{width:92%}.pro-bar.bar-91{width:91%}.pro-bar.bar-90{width:90%}.pro-bar.bar-89{width:89%}.pro-bar.bar-88{width:88%}.pro-bar.bar-87{width:87%}.pro-bar.bar-86{width:86%}.pro-bar.bar-85{width:85%}.pro-bar.bar-84{width:84%}.pro-bar.bar-83{width:83%}.pro-bar.bar-82{width:82%}.pro-bar.bar-81{width:81%}.pro-bar.bar-80{width:80%}.pro-bar.bar-79{width:79%}.pro-bar.bar-78{width:78%}.pro-bar.bar-77{width:77%}.pro-bar.bar-76{width:76%}.pro-bar.bar-75{width:75%}.pro-bar.bar-74{width:74%}.pro-bar.bar-73{width:73%}.pro-bar.bar-72{width:72%}.pro-bar.bar-71{width:71%}.pro-bar.bar-70{width:70%}.pro-bar.bar-69{width:69%}.pro-bar.bar-68{width:68%}.pro-bar.bar-67{width:67%}.pro-bar.bar-66{width:66%}.pro-bar.bar-65{width:65%}.pro-bar.bar-64{width:64%}.pro-bar.bar-63{width:63%}.pro-bar.bar-62{width:62%}.pro-bar.bar-61{width:61%}.pro-bar.bar-60{width:60%}.pro-bar.bar-59{width:59%}.pro-bar.bar-58{width:58%}.pro-bar.bar-57{width:57%}.pro-bar.bar-56{width:56%}.pro-bar.bar-55{width:55%}.pro-bar.bar-54{width:54%}.pro-bar.bar-53{width:53%}.pro-bar.bar-52{width:52%}.pro-bar.bar-51{width:51%}.pro-bar.bar-50{width:50%}.pro-bar.bar-49{width:49%}.pro-bar.bar-48{width:48%}.pro-bar.bar-47{width:47%}.pro-bar.bar-46{width:46%}.pro-bar.bar-45{width:45%}.pro-bar.bar-44{width:44%}.pro-bar.bar-43{width:43%}.pro-bar.bar-42{width:42%}.pro-bar.bar-41{width:41%}.pro-bar.bar-40{width:40%}.pro-bar.bar-39{width:39%}.pro-bar.bar-38{width:38%}.pro-bar.bar-37{width:37%}.pro-bar.bar-36{width:36%}.pro-bar.bar-35{width:35%}.pro-bar.bar-34{width:34%}.pro-bar.bar-33{width:33%}.pro-bar.bar-32{width:32%}.pro-bar.bar-31{width:31%}.pro-bar.bar-30{width:30%}.pro-bar.bar-29{width:29%}.pro-bar.bar-28{width:28%}.pro-bar.bar-27{width:27%}.pro-bar.bar-26{width:26%}.pro-bar.bar-25{width:25%}.pro-bar.bar-24{width:24%}.pro-bar.bar-23{width:23%}.pro-bar.bar-22{width:22%}.pro-bar.bar-21{width:21%}.pro-bar.bar-20{width:20%}.pro-bar.bar-19{width:19%}.pro-bar.bar-18{width:18%}.pro-bar.bar-17{width:17%}.pro-bar.bar-16{width:16%}.pro-bar.bar-15{width:15%}.pro-bar.bar-14{width:14%}.pro-bar.bar-13{width:13%}.pro-bar.bar-12{width:12%}.pro-bar.bar-11{width:11%}.pro-bar.bar-10{width:10%}.pro-bar.bar-9{width:9%}.pro-bar.bar-8{width:8%}.pro-bar.bar-7{width:7%}.pro-bar.bar-6{width:6%}.pro-bar.bar-5{width:5%}.pro-bar.bar-4{width:4%}.pro-bar.bar-3{width:3%}.pro-bar.bar-2{width:2%}.pro-bar.bar-1{width:1%}.pro-bar.bar-0{width:0}.pro-bar.color-turquoise{background:#1abc9c}.pro-bar.color-green-sea{background:#16a085}.pro-bar.color-emerald{background:#2ecc71}.pro-bar.color-nephritis{background:#27ae60}.pro-bar.color-peter-river{background:#3498db}.pro-bar.color-belize-hole{background:#2980b9}.pro-bar.color-amethyst{background:#9b59b6}.pro-bar.color-wisteria{background:#8e44ad}.pro-bar.color-wet-asphalt{background:#34495e}.pro-bar.color-midnight-blue{background:#2c3e50}.pro-bar.color-sun-flower{background:#f1c40f}.pro-bar.color-orange{background:#f39c12}.pro-bar.color-carrot{background:#e67e22}.pro-bar.color-pumpkin{background:#d35400}.pro-bar.color-alizarin{background:#e74c3c}.pro-bar.color-pomegranate{background:#c0392b}.pro-bar.color-clouds{background:#ecf0f1}.pro-bar.color-silver{background:#bdc3c7}.pro-bar.color-concrete{background:#95a5a6}.pro-bar.color-asbestos{background:#7f8c8d}@-webkit-keyframes progressStripeLTR{to{background-position:30px 0}}@-moz-keyframes progressStripeLTR{to{background-position:30px 0}}@-ms-keyframes progressStripeLTR{to{background-position:30px 0}}@-o-keyframes progressStripeLTR{to{background-position:30px 0}}@keyframes progressStripeLTR{to{background-position:30px 0}}@-webkit-keyframes progressStripeRTL{to{background-position:-30px 0}}@-moz-keyframes progressStripeRTL{to{background-position:-30px 0}}@-ms-keyframes progressStripeRTL{to{background-position:-30px 0}}@-o-keyframes progressStripeRTL{to{background-position:-30px 0}}@keyframes progressStripeRTL{to{background-position:-30px 0}}.pro-bar-candy{width:100%;height:15px;-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;background-image:-webkit-linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent);background-image:-ms-linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent);background-image:linear-gradient(-45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent);background-repeat:repeat-x;background-size:30px 30px}.pro-bar-candy.candy-ltr{-webkit-animation:progressStripeLTR .6s linear infinite;-moz-animation:progressStripeLTR .6s linear infinite;-ms-animation:progressStripeLTR .6s linear infinite;-o-animation:progressStripeLTR .6s linear infinite;animation:progressStripeLTR .6s linear infinite}.pro-bar-candy.candy-rtl{-webkit-animation:progressStripeRTL .6s linear infinite;-moz-animation:progressStripeRTL .6s linear infinite;-ms-animation:progressStripeRTL .6s linear infinite;-o-animation:progressStripeRTL .6s linear infinite;animation:progressStripeRTL .6s linear infinite}
</style>
</head>
<body>
<script type="text/javascript">
document.body.appendChild(
pieChart([12,23,34],130,210,60,60,50,
["#06D6A0","#AC4EDD","#02A6D1"],
["North","South","East"],20,130));
/**
* 创建一个<svg>元素,并在其中绘制一个饼状图
* 参数:
* data:用于绘制的数字类型的数组,数组每一项都表示饼状图的一个楔
* width,height: SVG图形的大小,单位为像素
* cx cy r : 饼状图的圆心及半径
* colors: 一个包含HTML颜色信息的数组,每种颜色代表饼状图每个楔的颜色
* labels: 一个标签数组,该信息说明饼状图中每个楔代表的含义
* lx ly: 饼状图的左上角
* 返回:
* 一个保存饼状图的<svg>元素
* 调用者必须将返回的元素插入到文档中
*/
function pieChart( data , width,height,cx,cy,r,colors,labels,lx,ly){
//这个是表示svg元素的XML命名空间
var svgns = "http://www.w3.org/2000/svg";
//创建一个<svg>元素,同时制定像素大小和用户坐标
var chart = document.createElementNS(svgns,"svg:svg");
chart.setAttribute("width",width);
chart.setAttribute("height",height);
chart.setAttribute("viewBox","0 0 "+width+" "+height);
//累加data的值,以便于知道饼状图的大小
var total = 0;
for(var i = 0 ; i < data.length ; i++)
total += data[i];
//现在计算出饼状图每个分片的大小,其中角度以弧度制计算
var angles = [];
for( var i = 0; i<data.length ; i++)
angles[i] = data[i]/total*Math.PI*2;
//遍历饼状图的每个分片
startangle = 0 ;
for(var i = 0 ; i < data.length ; i++){
//这里表示楔的结束位置
var endagle = startangle+angles[i];
//计算出楔和园相交的两个点
//这些计算公式都是以12点钟方向为0度
//顺时针方向角度递增
var x1 = cx+r*Math.sin(startangle);
var y1 = cy-r*Math.cos(startangle);
var x2 = cx+r*Math.sin(endagle);
var y2 = cx-r*Math.cos(endagle);
//这个标记表示角度大于半圆
//此标记在绘制svg弧形组件的时候需要
var big = 0;
if(endagle - startangle > Math.PI)
big = 1;
//使用<svg:path>元素来描述楔
//要注意的是,使用createElementNS()来创建该元素
var path = document.createElementNS(svgns , "path");
//下面的字符串包含路径的详细信息
var d= "M " + cx + "," + cy + //从圆心开始
" L " + x1 + "," + y1 + //画一条到(x1,y1)的线段
" A " + r + "," + r + //再画一条半径为r的弧
" 0 " + big + " 1 " + //弧的详细信息
x2 + "," + y2 + //弧到(x2,y2)结束
" Z"; //当前路径到(cx,cy)结束
//设置<svg:path>元素的属性
path.setAttribute("d",d); //设置路径
path.setAttribute("fill",colors[i]); //设置楔的颜色
path.setAttribute("stroke","black"); //楔的外边框为黑色
path.setAttribute("stroke-width","1"); //两个单位宽
chart.appendChild(path); //将楔加入到饼状图中
//当前楔的结束就是下一个楔的开始
startangle = endagle;
//现在绘制一些相应的小方块来表示图例
var icon = document.createElementNS(svgns,"rect");
icon.setAttribute("x",lx); //定位小方块
icon.setAttribute("y",ly+20*i);
icon.setAttribute("width",10); //设置小方块的大小
icon.setAttribute("height",10);
icon.setAttribute("fill",colors[i]); //填充小方块的颜色和对应的楔的颜色相同
icon.setAttribute("stroke","black"); //子外边框颜色也相同
icon.setAttribute("stroke-width","2"); //两个单位宽
chart.appendChild(icon); //添加到饼状图中
//在小方块的右边添加标签
var label = document.createElementNS(svgns,"text");
label.setAttribute("x",lx+20); //定位标签文本
label.setAttribute("y",ly+20*i+10);
//文本样式属性还可以通过CSS来设置
label.setAttribute("font-size","16");
label.setAttribute("font-family","sans-serif");
//在<svg:text>元素中添加一个DOM文本节点
label.appendChild(document.createTextNode(labels[i]));
chart.appendChild(label); //将文本添加到饼状图中
}
return chart;
}
</script>
</body>
</html>